From: Frédéric Lécaille Date: Mon, 6 Nov 2023 13:16:10 +0000 (+0100) Subject: BUG/MINOR: quic: idle timer task requeued in the past X-Git-Tag: v2.9-dev10~127 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7ecf4b34b94e3f2ee4edb6025f86e9b6997be5fa;p=thirdparty%2Fhaproxy.git BUG/MINOR: quic: idle timer task requeued in the past When the idle timer expired with a still present mux, this task was not freed and even requeued with a timer in the past. Fix this issue calling task_destroy() in this case. As the task is freed, its handler must return NULL setting local variable to NULL in every cases. Also ensure that this timer task is not armed again after having been released with a statement when this is the case from qc_idle_timer_do_rearm(). Must be backported as far as 2.6. --- diff --git a/src/quic_conn.c b/src/quic_conn.c index d5d5adeaf8..69fa996ca8 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -1573,6 +1573,10 @@ void qc_idle_timer_do_rearm(struct quic_conn *qc, int arm_ack) { unsigned int expire; + /* It is possible the idle timer task has been already released. */ + if (!qc->idle_timer_task) + return; + if (stopping && qc->flags & (QUIC_FL_CONN_CLOSING|QUIC_FL_CONN_DRAINING)) { TRACE_PROTO("executing idle timer immediately on stopping", QUIC_EV_CONN_IDLE_TIMER, qc); qc->ack_expire = TICK_ETERNITY; @@ -1685,8 +1689,13 @@ struct task *qc_idle_timer_task(struct task *t, void *ctx, unsigned int state) if (qc->mux_state != QC_MUX_READY) { quic_conn_release(qc); qc = NULL; - t = NULL; } + else { + task_destroy(t); + qc->idle_timer_task = NULL; + } + + t = NULL; /* TODO if the quic-conn cannot be freed because of the MUX, we may at * least clean some parts of it such as the tasklet.