On Fri, Mar 27, 2026 at 04:46:56PM -0700, Cody Ohlsen wrote:
> Hi Christopher,
> 
> Thanks for the review and the suggested adaptation. I will certainly
> resubmit the patch based on your proposal. I verified it would work in the
> situation we were describing, and it definitely makes sense and seems like
> an improvement. Appreciate your help.
> 
> However - I want to share additional context about our trigger scenario,
> since it may affect the severity assessment. Our setup is H1.1 frontend ->
> H2 backend (reverse proxy to an S3-style storage system). HEAD requests are
> used for metadata checks (content-length, object existence). I _think_ our
> H2 backend responds to HEAD with:
> 
>   1. HEADERS frame (status + content-length, NO END_STREAM)
>   2. DATA frame (0 bytes payload, END_STREAM)

It very possibly makes a difference, you're right!

> I suspect that when these frames arrive in separate TCP segments
> (timing-dependent, but happens in practice on all requests), the H2 demux
> processes HEADERS first, notifies the stream (deferred via
> tasklet_wakeup_after), and process_stream forwards headers to the H1
> frontend without EOM. At that point htx_expect_more() returns true,
> CO_SFL_MSG_MORE propagates to h1_snd_buf(), and the kernel corks for ~200ms
> waiting for body data that will never come.
> 
> The fix (as well as your suggested fix) addresses this path. But I suspect
> no body payload is needed in the channel, just the absence of EOM when
> headers are first forwarded.
> 
> For H1 backends, h1_postparse_res_hdrs() correctly sets HTX_FL_EOM during
> header parsing for HEAD responses, eliminating the timing dependency
> entirely. I _think_ this explains why reproduction requires set-method GET
> with H1 backends - the bug is latent with H1 (unless you add http-request
> set-method GET), but I think often (or perhaps always) active with H2
> backend.

I'm suspecting that the root cause is in fact the complex condition in
sc_conn_send() that computes the send_flag. Historically these flags
were set at the high level because we wanted the ability to merge the
shut with the H1 response for example (and this test is still present),
but nowadays some of these tests are no longer relevant at this layer.
Typically the test for the shut flag makes sense for H1 but not for H2/H3
where it would be turned into a flag that would be merged with the HEADERS
frame. htx_expect_more() checks for HTX_EOM that the mux can figure by
itself.

I suspect that the condition can indeed be wrong sometimes for bodyless
responses (HEAD, 204, 304) if EOM is not there or maybe if a content-length
is advertised (HEAD/304) or just absent from the response. It's not a big
problem, it's just something to keep in our radar of stuff to be improved.
I think that instead of passing just CO_SFL_MSG_MORE we should probably
have a few more flags to pass more info down to the mux to indicate if
more body is really expected, if a shut is in sight, etc so that the mux
has more info to take such decisions which would be more suited to the
protocol.

> I am wondering - in your test, did you happen to have an H2 backend? or an
> H1.1 backend. Thanks.
> 
> Regardless, I verified that the adapted patch solves our issue - I really
> appreciate your help and feedback - thanks again! I will re-submit the
> updated patch as suggested.
> 
> - Cody

Thanks!
Willy


Reply via email to