Propagate cancellation through HTTP/2 output - #250
Merged
Conversation
tavianator
force-pushed
the
mitigate-shutdown-hang
branch
from
September 9, 2026 14:40
448a670 to
92b8590
Compare
The `ensure` block in `passthrough` attempts to close the stream with
`self.close_write(error)`, but there are two issues:
- For a cancelled task, `error` will be `nil` since it won't get set by
the `rescue => error` block, as `Async::Cancel` isn't a `StandardError`
- More seriously, the actual `write()` can block indefinitely, stalling
reactor shutdown
This led to backtraces like this during Falcon worker shutdown, forcing
Falcon to `SIGKILL` the worker process after the timeout:
async-2.45.1 async/scheduler.rb:382 IO::Event::Selector::URing#io_write
async-2.45.1 async/scheduler.rb:382 Async::Scheduler#io_write
io-stream-0.11 io/stream/buffered.rb:112 IO#write
io-stream-0.11 io/stream/buffered.rb:112 IO::Stream::Buffered#syswrite
io-stream-0.11 io/stream/writable.rb:99 IO::Stream::Writable#drain
io-stream-0.11 io/stream/writable.rb:47 block in IO::Stream::Writable#flush
io-stream-0.11 io/stream/writable.rb:46 Thread::Mutex#synchronize
io-stream-0.11 io/stream/writable.rb:46 IO::Stream::Writable#flush
protocol-http2 protocol/http2/framer.rb:58 Protocol::HTTP2::Framer#flush
protocol-http2 protocol/http2/connection.rb:253 Protocol::HTTP2::Connection#write_frame
protocol-http2 protocol/http2/stream.rb:115 Protocol::HTTP2::Stream#write_frame
protocol-http2 protocol/http2/stream.rb:203 Protocol::HTTP2::Stream#write_data
protocol-http2 protocol/http2/stream.rb:213 Protocol::HTTP2::Stream#send_data
async-http-0.94.2 http2/stream.rb:140 Async::HTTP::Protocol::HTTP2::Stream#finish_output
async-http-0.94.2 http2/output.rb:68 Async::HTTP::Protocol::HTTP2::Output#close_write
async-http-0.94.2 http2/output.rb:120 Async::HTTP::Protocol::HTTP2::Output#passthrough
async-2.45.1 async/task.rb:225 block in Async::Task#run
async-2.45.1 async/task.rb:523 block in Async::Task#schedule
Fix this with `rescue Exception => error`, and add a 1-second timeout
around `close_write` if `error` is non-`nil`.
tavianator
force-pushed
the
mitigate-shutdown-hang
branch
from
September 9, 2026 15:25
92b8590 to
1aed35c
Compare
Signed-off-by: Samuel Williams <samuel.williams@shopify.com> Assisted-By: devx/2fb5639b-d636-44ad-a666-9088d8c41cc1
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.
The
ensureblock inOutput#passthroughcallsclose_write(error), but a cancelled task previously lefterrorasnil: a barerescue => errorcatchesStandardError, whileAsync::Cancelinherits directly fromException.As a result, cancellation was presented to
finish_outputas orderly completion. Explicitly rescueAsync::CancelalongsideStandardError, preserving the cancellation object for body and stream cleanup before re-raising it.This change intentionally does not add timeout or forced transport-abort policy. It only corrects cancellation propagation.
Types of Changes
Contribution