]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: quic: idle timer task requeued in the past
authorFrédéric Lécaille <flecaille@haproxy.com>
Mon, 6 Nov 2023 13:16:10 +0000 (14:16 +0100)
committerFrédéric Lécaille <flecaille@haproxy.com>
Thu, 9 Nov 2023 09:32:31 +0000 (10:32 +0100)
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 <t> variable to NULL in every cases.

Also ensure that this timer task is not armed again after having been released
with a <return> statement when this is the case from qc_idle_timer_do_rearm().

Must be backported as far as 2.6.

src/quic_conn.c

index d5d5adeaf832074133d36bc6e9c29089f65c4dfa..69fa996ca8ac2fe8e85c6b4d01460afb611aba2d 100644 (file)
@@ -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.