Skip to content

Race condition in HeaderWriterFilter when returning StreamingResponseBody in Spring MVC #33304

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
chschu opened this issue Aug 2, 2024 · 3 comments
Labels
for: external-project Needs a fix in external project in: web Issues in web modules (web, webmvc, webflux, websocket)

Comments

@chschu
Copy link

chschu commented Aug 2, 2024

Affects: 6.0.x, 6.1.x (list is not exhaustive)

When using HeaderWriterFilter and controller methods that return StreamingResponseBody, headers may be set twice.

The following two things happen in parallel:

  • The asynchronous processing of the StreamingResponseBody. If enough data is transferred to the response body, the response is forcefully committed. This causes the HeaderWriterFilter to write headers from the asynchronous thread.
  • The synchronous execution of the HeaderWriterFilter, which will write headers from the request handling thread.

Both threads may successfully pass the isDisableOnResponseCommitted() check in HeaderWriterFilter.HeaderWriterResponse#writeHeaders, causing the HeaderWriters to be invoked twice. This alone may already cause duplicate headers.

It gets even worse: The implementation of HttpServletResponse is not guaranteed to be thread safe according to the Servlet Spec.

When using Apache Tomcat, adding headers in parallel causes nasty race conditions (visible as NullPointerExceptions) that (because of garbage avoidance) may permanently break the inner workings of their org.apache.tomcat.util.http.MimeHeaders class, leading to strange errors in threads that use recycled response instances.

My current workaround: Write all headers and flush the response in the handler method.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Aug 2, 2024
@bclozel bclozel added the in: web Issues in web modules (web, webmvc, webflux, websocket) label Aug 2, 2024
@snicoll
Copy link
Member

snicoll commented Aug 2, 2024

Thanks for the report and the analysis. HeaderWriterFilter is part of Spring Security, did you mean to report the issue there? If not, we'd need a small sample that reproduces what you've described.

You can attach a zip here with instructions to reproduce or push the code with a readme on a GitHub repository. Thank you.

@snicoll snicoll added the status: waiting-for-feedback We need additional information before we can continue label Aug 2, 2024
@chschu
Copy link
Author

chschu commented Aug 2, 2024

You're right, I simply didn't notice that HeaderWriterFilter is located in Spring Security. I'll report the issue there.

@chschu chschu closed this as completed Aug 2, 2024
@snicoll snicoll closed this as not planned Won't fix, can't repro, duplicate, stale Aug 2, 2024
@snicoll snicoll added for: external-project Needs a fix in external project and removed status: waiting-for-feedback We need additional information before we can continue status: waiting-for-triage An issue we've not yet triaged or decided on labels Aug 2, 2024
@chschu
Copy link
Author

chschu commented Aug 2, 2024

Reported as spring-projects/spring-security#15510 with additional information and a reproducer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: external-project Needs a fix in external project in: web Issues in web modules (web, webmvc, webflux, websocket)
Projects
None yet
Development

No branches or pull requests

4 participants