]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MEDIUM: mux-h2: wake the connection up after a delayed mbuf allocation
authorWilly Tarreau <w@1wt.eu>
Tue, 6 Oct 2026 20:31:50 +0000 (22:31 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 9 Nov 2026 19:48:35 +0000 (20:48 +0100)
When the mux buffer couldn't be allocated, H2_CF_MUX_MALLOC is set, the
streams that were trying to send are marked H2_SF_BLK_MROOM, and the
connection is queued in the buffer wait list. Once h2_buf_available()
manages to allocate the buffer, it clears the flag but only wakes the
connection up if the demux was also blocked (H2_CF_DEM_MROOM), which is
only the case for control frames (ACKs, WU, RST etc). When only streams
were blocked (e.g. a response HEADERS frame), nothing resumes them, and
they remain blocked until another event happens on the connection, or
until the timeout strikes.

This was reproduced with a debug patch faking a failed mbuf allocation
when sending the response HEADERS frame of an H2 request forwarded to
a server, and calling offer_buffers() 200ms later: the request hangs
until the client gives up after 5s, while it completes in 200ms once the
tasklet is woken up, since h2_send() resumes the streams waiting in the
send list.

This was introduced in 1.9 by commit 53216e7db ("MEDIUM: connections:
Don't directly mess with the polling from the upper layers.") which
removed the conn_xprt_want_send() call without replacing it. It requires
a buffer allocation failure to happen first so it's quite rare. This may
be backported to all supported versions.

src/mux_h2.c

index 3a5aff4150e7796a95973950bc317542dd8cc381..691dd5afe45fea3465dbc907767a05be5ad064c3 100644 (file)
@@ -1283,6 +1283,8 @@ static int h2_buf_available(void *target)
                        h2c->flags &= ~H2_CF_DEM_MROOM;
                        h2c_restart_reading(h2c, 1);
                }
+               /* streams blocked on the mbuf are resumed by h2_send() */
+               tasklet_wakeup(h2c->wait_event.tasklet);
                return 1;
        }