From: Amaury Denoyelle Date: Thu, 23 Apr 2026 13:32:58 +0000 (+0200) Subject: BUG/MINOR: mux_quic: do not release conn on qcc_recv() for QMux X-Git-Tag: v3.4-dev10~69 X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=d7e3b826f2035f692aac1cb8659588f6b323ae83;p=haproxy.git BUG/MINOR: mux_quic: do not release conn on qcc_recv() for QMux Recently, an extra check has been added so that a dead connection is immediately release on at the end of qcc_recv() operation. This is useful when a GOAWAY frame is received from a server, so that the backend connection is released if idle. This step is in fact only necessary for QUIC, as qcc_recv() is called directly from the lower transport layer. It causes issues with QMux as in this case qcc_recv() is called via qcc_io_recv(). A crash in this context will occur as qcc_recv() does not indicate that a release has been performed. To fix this, simply disable the extra check at the end of qcc_recv() for QMux. This is fine as in this case receive operation is always followed by qcc_io_process() which is able to release the connection in a safe way. No need to backport. --- diff --git a/src/mux_quic.c b/src/mux_quic.c index dcabe1ea9..c0e41a26c 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -2036,8 +2036,12 @@ int qcc_recv(struct qcc *qcc, uint64_t id, uint64_t len, uint64_t offset, BUG_ON_HOT(fin_standalone); /* On fin_standalone should be NULL, which ensures no infinite loop. */ } - /* Ensure that an idle backend conn is freed if it cannot open new stream. */ - if (conn_is_back(qcc->conn) && qcc_is_dead(qcc)) { + /* Ensure that an idle backend conn is freed if it cannot open new + * stream. This is only performed for QUIC which directly calls + * qcc_recv() and is not compatible with QMux. For the latter, dead + * connection should still be detected after recv via qcc_io_process(). + */ + if (conn_is_quic(qcc->conn) && conn_is_back(qcc->conn) && qcc_is_dead(qcc)) { TRACE_STATE("releasing dead connection after STREAM decoding", QMUX_EV_QCC_RECV, qcc->conn); qcc_release(qcc); return 0;