Skip to content

Allow HTTP/2 frames to be written from a fiber which is not a task - #258

Open
andrewfader wants to merge 1 commit into
socketry:mainfrom
andrewfader:http2-writes-outside-task
Open

andrewfader wants to merge 1 commit into
socketry:mainfrom
andrewfader:http2-writes-outside-task

Conversation

@andrewfader

Copy link
Copy Markdown

The HTTP/2 connection's write_frame and write_frames call Task.current.defer_stop, which raises RuntimeError: No async task available! on a fiber that runs under the scheduler but isn't an Async task. An Enumerator is the common case: its fiber inherits the scheduler, so reading a response body from it works until the client needs to send a WINDOW_UPDATE (or an RST_STREAM when the body is closed early), and then the write fails.

We hit this in production under Falcon: a Rack response body proxies an upstream HTTP/2 download, and the server iterates that body through an Enumerator. Downloads failed a few MB in, once the client's window needed extending.

With no task there is nothing to defer stopping, so the writes now use Task.current? and write directly when it's nil.

The new test reads a 10 MB response through an Enumerator. Without the change it fails with No async task available! from Input#read → request_window_update → write_frame; with it the whole body is read. bundle exec sus (276 passed, 3 skipped) and bundle exec rubocop are clean.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant