Conversation
158aa40 to
1c5b346
Compare
1c5b346 to
be3fdf6
Compare
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.
When an HTTP/2 client resets a stream before the server sends response headers (common with gRPC cancellation),
request.send_response(response)raisesProtocolError: Cannot send headers in state: closed. The response body is never closed because there is noensureguard on the send path. Any resources tied to body lifecycle — such asrack.response_finishedcallbacks and utilization metrics — are permanently leaked.This was discovered via Falcon's
requests_activeutilization metric (tracked byBody::RequestFinished), which was never decremented on this error path. On clusters with gRPC traffic, eachProtocolErrorleaked +1 intorequests_activepermanently, producing a monotonically increasing gauge.The fix adds
ensure response&.closeinServer#each, bringing the HTTP/2 server to parity with the HTTP/1 server which already had equivalentensure body&.close(error)handling. The call is safe on all paths: on success the body is already closed bysend_bodyandcloseis idempotent; onyieldfailureresponseisnilso the call is a no-op; on task cancellationensurestill runs afterdefer_stop.Types of Changes
Contribution