Skip to content

Comments

Update connection window size, before any stream specific handling#12910

Open
yknoya wants to merge 1 commit intoapache:9.2.xfrom
yknoya:fix/h2-post-timeout/window-decrement-timing
Open

Update connection window size, before any stream specific handling#12910
yknoya wants to merge 1 commit intoapache:9.2.xfrom
yknoya:fix/h2-post-timeout/window-decrement-timing

Conversation

@yknoya
Copy link
Contributor

@yknoya yknoya commented Feb 24, 2026

Issue

In ATS 9.2.x, we observed an increase in 408/504 (timeout) responses for HTTP/2 POST requests.
Although simplified, the issue occurs when all of the following conditions are met:

  1. Multiple POST requests are sent over a single HTTP/2 connection.
  2. ATS fails to connect to the origin during processing and returns a 502 response.
  3. When the second condition occurs, the connection-level window size tracked by the client for ATS becomes 0.

This issue was resolved when the HTTP/2 to origin feature was implemented.
Therefore, it reproduces on the 9.2.x branch, but not on the following branches:

  • master
  • 10.1.x

Root Cause

In conclusion, the issue is caused by a mismatch in the connection-level window size between the client and ATS.
The client's tracked window size reaches 0, while ATS internally maintains a value greater than 0.

More specifically, when handling multiple POST requests, the timeout occurs through the following sequence:

  1. The client sends a HEADERS frame.
  2. ATS receives the HEADERS frame.
  3. ATS attempts to connect to the origin but fails.
  4. ATS sends a 502 response (HEADERS frame) to the client.
  5. ATS closes the stream.
  6. ATS receives a DATA frame from the client.
  7. Since the stream is already closed, ATS sends a RST_STREAM frame to the client. (The connection-level window size on the ATS side is not decremented.)
  8. Steps 6 and 7 are repeated multiple times, eventually causing the client's tracked window size for ATS to reach 0.
  9. The client stops sending DATA frames because the window size has reached 0.
  10. ATS determines that sufficient window size remains and does not send a WINDOW_UPDATE frame.
  11. The client continues waiting for a WINDOW_UPDATE frame and eventually times out.

Although the stream has already been closed, the root cause is that ATS does not decrement the connection-level window size when it receives a DATA frame for a closed stream.

Fix

In the 10.1.x branch, the timing of the connection-level window size decrement was moved earlier in the processing flow.
The same change has been applied to the 9.2.x branch.

Http2StreamDebug(this->session, id, "Received DATA frame, flags: %d", frame.header().flags);
// Update connection window size, before any stream specific handling
this->decrement_local_rwnd(payload_length);
if (this->get_zombie_event()) {
Warning("Data frame for zombied session %" PRId64, this->session->get_connection_id());
}

@yknoya yknoya marked this pull request as ready for review February 24, 2026 08:48
@yknoya yknoya requested a review from masaori335 as a code owner February 24, 2026 08:48
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