Skip to content

server: keep the small-frames test inside h2's data-frame budget - #319

Merged
iainmcgin merged 1 commit into
mainfrom
iain/h2-small-frames-test
Sep 22, 2026
Merged

iainmcgin merged 1 commit into
mainfrom
iain/h2-small-frames-test

Conversation

@iainmcgin

@iainmcgin iainmcgin commented Sep 22, 2026 •

Copy link
Copy Markdown
Collaborator

http2_early_return_keeps_connection_alive_under_small_frames (from #313) fails most merge-queue runs on loaded 2-core runners with "calls were lost". The server is not timing out: it sends GOAWAY(ENHANCE_YOUR_CALM, "too_many_data_frames"). Pinned to one or two CPUs locally, the test failed 62 of 64 runs, every time on that GOAWAY or the broken pipe after it. h2 (0.4.16 and later) charges each non-final DATA frame under 256 bytes 256 - len against a connection budget of max(initial window / 2, 25,600) until the application reads it, and a busy reader can leave a whole connection window unread. A window's worth of the test's 105-byte frames costs about three times that budget.

The test now pins the server's connection window at 65,535 bytes and sends 185-byte frames whole, so a full window of unread frames costs 25,134, under the 25,600 minimum. With these changes it passed 190 of 190 contended runs, and it still fails against a reader that drops the body as soon as the handler returns. The spawn_body_reader doc comment, which said only frames of 256 bytes or more refill the budget, now says the charge is refunded when the frame is read or discarded.

The same limit applies outside the test: one client-streaming call whose handler waits 2 s before reading loses its connection at about 300 small frames, and hyper does not expose h2's budget setting.

`http2_early_return_keeps_connection_alive_under_small_frames` failed
on loaded machines with `GOAWAY(ENHANCE_YOUR_CALM, "too_many_data_frames")`.
h2 charges each small DATA frame against a connection-wide budget until
it is read, including frames that are only waiting for a busy reader. A
connection window's worth of the test's 105-byte frames costs about
three times the budget, and the adaptive window lets the window grow
further. The callers then returned silently, so the failure read as
"calls were lost".

The server's connection window is now pinned at 65,535 bytes and each
frame carries 185 bytes, sent as a single DATA frame. A full window of
unread frames then costs 25,134, under h2's minimum budget of 25,600.
The callers fail with the h2 error instead of returning, and the test
still fails against a reader that stops reading as soon as the handler
returns.

Signed-off-by: Iain McGinniss <309153+iainmcgin@users.noreply.github.com>
@iainmcgin
iainmcgin marked this pull request as ready for review September 22, 2026 17:08
@iainmcgin
iainmcgin added this pull request to the merge queue Sep 22, 2026
Merged via the queue into main with commit 3309f9b Sep 22, 2026
14 checks passed
@iainmcgin
iainmcgin deleted the iain/h2-small-frames-test branch September 22, 2026 17:15
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.

2 participants