From 7ecf4b34b94e3f2ee4edb6025f86e9b6997be5fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20L=C3=A9caille?= Date: Mon, 6 Nov 2023 14:16:10 +0100 Subject: [PATCH] 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. --- src/quic_conn.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/quic_conn.c b/src/quic_conn.c index d5d5adeaf..69fa996ca 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.