From: Willy Tarreau Date: Tue, 6 Oct 2026 20:31:50 +0000 (+0200) Subject: BUG/MEDIUM: mux-h2: wake the connection up after a delayed mbuf allocation X-Git-Url: https://git.kaiwu.me/$%7BISSUES%7D/static/gitweb.js?a=commitdiff_plain;h=916c43d290c435d8e1dcc1122031cf448b0b41d2;p=haproxy.git BUG/MEDIUM: mux-h2: wake the connection up after a delayed mbuf allocation 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. --- diff --git a/src/mux_h2.c b/src/mux_h2.c index 3a5aff415..691dd5afe 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -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; }