From 419cc6e2f6d2bb8fd1a761ecb44ce9730bcbcb3e Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Thu, 30 Apr 2026 17:47:28 +0200 Subject: [PATCH] BUG/MINOR: mux_quic: refresh timeout only if I/O performed Previously, QUIC MUX timeout was refreshed on every qcc_io_cb() execution. This is not desired if no send/receive were performed, as in this case the connection may be stuck. This patch fixes this by refreshing timeout only if some progress is performed during qcc_io_cb(). To implement this, return value of qcc_io_recv() has been adjusted to return the number of newly decoded bytes. This patch is considered as a bug fix as without it there is a risk of QUIC MUX inactivity timeout to be less efficient and to maintain a connection too long. This should be backported up to 2.8, after a period of observation. --- src/mux_quic.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/mux_quic.c b/src/mux_quic.c index ff2f9523d..7a1500db8 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -3247,12 +3247,12 @@ static void qcc_wait_for_hs(struct qcc *qcc) /* Proceed on receiving. Loop on streams subscribed in recv_list and performed * STREAM frames decoding upon them. * - * Returns 0 on success else non-zero. + * Returns the number of newly transcoded bytes. */ static int qcc_io_recv(struct qcc *qcc) { struct qcs *qcs; - int ret; + int total = 0, ret; TRACE_ENTER(QMUX_EV_QCC_RECV, qcc->conn); @@ -3281,12 +3281,13 @@ static int qcc_io_recv(struct qcc *qcc) if (ret <= 0) goto done; + total += ret; } } done: TRACE_LEAVE(QMUX_EV_QCC_RECV, qcc->conn); - return 0; + return total; } /* Calculate the number of bidirectional streams which can still be opened for @@ -3613,7 +3614,7 @@ struct task *qcc_io_cb(struct task *t, void *ctx, unsigned int state) { struct qcc *qcc = ctx; struct connection *conn; - int conn_in_list; + int total = 0, conn_in_list; if (state & TASK_F_USR1) { /* the tasklet was idling on an idle connection, it might have @@ -3661,16 +3662,17 @@ struct task *qcc_io_cb(struct task *t, void *ctx, unsigned int state) } if (!(qcc->wait_event.events & SUB_RETRY_SEND)) - qcc_io_send(qcc); + total += qcc_io_send(qcc); - qcc_io_recv(qcc); + total += qcc_io_recv(qcc); if (qcc_io_process(qcc)) { TRACE_STATE("releasing dead connection", QMUX_EV_QCC_WAKE, conn); goto release; } - qcc_refresh_timeout(qcc); + if (total) + qcc_refresh_timeout(qcc); /* Trigger pacing task is emission should be retried after some delay. */ if (qcc_is_pacing_active(conn)) {