]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: mux_quic: do not release conn on qcc_recv() for QMux
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 23 Apr 2026 13:32:58 +0000 (15:32 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 24 Apr 2026 07:33:04 +0000 (09:33 +0200)
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.

src/mux_quic.c

index dcabe1ea9e845175fcf02038098ea22ce48ba177..c0e41a26cc7b0e7787ee323386e85b71a9fc041a 100644 (file)
@@ -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 <ret> 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;