Skip request body drain when connection will close#2504
Merged
yhirose merged 2 commits intoJul 22, 2026
Conversation
The post-response drain exists to keep unread framed body bytes from being parsed as a subsequent request on a persistent connection. Once response generation has committed the connection to close, there can be no subsequent request, so draining no longer provides that protection. Continuing to drain is especially harmful when a ContentReader aborts an unterminated chunked upload: the server can wait indefinitely for the terminal chunk even after sending Connection: close. This delays the transport close that tells an in-flight uploader to stop and leaves a worker occupied consuming discarded data. Use the finalized response Connection header as the single source of truth for whether to skip the drain. write_response_core already sets this header for keep-alive exhaustion, request-directed closure, handler-directed closure, and error responses. Marking connection_closed then terminates the keep-alive loop and closes the socket. Add a raw-socket regression test whose ContentReader rejects the first chunk of an unterminated upload. The test verifies that the 409 response announces Connection: close and that the peer observes EOF rather than timing out while the server drains.
Owner
|
@emreay- thanks for this PR. Could you please take a look at the |
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Owner
|
@emreay- thanks for this fine contribution! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Skip draining an unconsumed framed request body when the response has already committed the connection to close.
The post-response drain prevents unread body bytes from being parsed as the next request on a keep-alive connection. When the response contains
Connection: close, there is no next request to protect.Problem
If a
ContentReaderaborts an unterminated chunked upload, the current drain waits for the terminal chunk after sending the response. A client that keeps producing chunks continually resets the read timeout, so:This also means the server can send
Connection: closewhile continuing to consume the request indefinitely.Fix
Use the finalized response header as the close decision:
write_response_corealready sets this header for keep-alive exhaustion, request-directed closure, handler-directed closure, and error responses. Reusable connections retain the existing drain behavior.Relationship to #2450
This is a follow-up to #2450:
Both changes restrict the drain to cases where it can serve its request-smuggling-prevention purpose.
Test
A raw-socket regression test sends an unterminated chunked request whose
ContentReaderrejects the first chunk. It verifies that the client receives the409 Connection: closeresponse followed by EOF.On unpatched
master, the finalrecvtimes out because the server remains in the drain. With this change, it returns0immediately.The new test and the existing #2450 regression both pass on Windows with MSVC.