]> git.kaiwu.me - haproxy.git/commit
BUG/MINOR: mux-h2: unblock the demux when destroying the stream it was blocked on
authorWilly Tarreau <w@1wt.eu>
Tue, 6 Oct 2026 20:53:29 +0000 (22:53 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 9 Nov 2026 19:48:35 +0000 (20:48 +0100)
commit01bdaab38f54f2bd46fb035924ef9a6e60979460
tree36a723eb6db7d5ab9918a7c607a16b2d7dfac727
parentbb18c754ee60c4cd09a43fd49fec09942f6df0b1
BUG/MINOR: mux-h2: unblock the demux when destroying the stream it was blocked on

When the demux is blocked on a stream whose rxbufs are full, it sets
H2_CF_DEM_SFULL and waits for h2_rcv_buf() to make room. If the upper
layer leaves at this moment, h2_detach() normally clears the demux
blocking flags when the stream is the one being demuxed. But if the
stream could not send its RST_STREAM (or ES) at shutdown time because the
mux buffer was full, h2_detach() leaves early to keep the stream as an
orphan, and skips that part. The stream is later destroyed by
h2_deferred_shut() once the frame can be sent, but h2s_destroy() only
unblocks the demux if it was waiting for rxbuf slots (H2_CF_DEM_RXBUF),
not if it was waiting for this stream's buffers to be drained
(H2_CF_DEM_SFULL). The demux thus remains blocked until the timeout
triggers.

This requires an upload on a stream whose upper layer aborts (e.g. server
timeout or error) while the client is not reading its responses fast
enough for the RST_STREAM to be sent. It was reproduced with a debug patch
simulating a full mux buffer when sending the RST_STREAM of the stream
the demux is blocked on, with an H2 client uploading to a server which
never reads (timeout server 2s), then sending a GET on another stream of
the same connection: the GET never gets a response, while it gets a 200
immediately with the fix.

The fix consists in also clearing H2_CF_DEM_SFULL in h2s_destroy() when
the destroyed stream is the one the demux is blocked on. The issue seems
to exist since orphaned streams are destroyed from h2_deferred_shut()
(1.9). The fix may be backported to all supported versions, though before
3.1 the rxbuf release code differs and the same test must be applied after
releasing the stream's rxbuf.
src/mux_h2.c