From faa18c1ad878ae8de44df876bd1390a2d71d6982 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Thu, 1 May 2025 14:39:39 +0200 Subject: [PATCH] BUG/MEDIUM: quic: Let it be known if the tasklet has been released. quic_conn_release() may, or may not, free the tasklet associated with the connection. So make it return 1 if it was, and 0 otherwise, so that if it was called from the tasklet handler itself, the said handler can act accordingly and return NULL if the tasklet was destroyed. This should be backported if 9240cd4a2771245fae4d0d69ef025104b14bfc23 is backported. --- include/haproxy/quic_conn.h | 2 +- src/quic_conn.c | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/haproxy/quic_conn.h b/include/haproxy/quic_conn.h index 3ba4b0938..b6a416644 100644 --- a/include/haproxy/quic_conn.h +++ b/include/haproxy/quic_conn.h @@ -174,7 +174,7 @@ int qc_notify_send(struct quic_conn *qc); void qc_check_close_on_released_mux(struct quic_conn *qc); -void quic_conn_release(struct quic_conn *qc); +int quic_conn_release(struct quic_conn *qc); void qc_kill_conn(struct quic_conn *qc); diff --git a/src/quic_conn.c b/src/quic_conn.c index 882158c76..5b04dbfc1 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -625,8 +625,8 @@ struct task *quic_conn_app_io_cb(struct task *t, void *context, unsigned int sta out: if ((qc->flags & QUIC_FL_CONN_CLOSING) && qc->mux_state != QC_MUX_READY) { - quic_conn_release(qc); - t = NULL; + if (quic_conn_release(qc)) + t = NULL; qc = NULL; } @@ -904,7 +904,8 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state) } if ((qc->flags & QUIC_FL_CONN_CLOSING) && qc->mux_state != QC_MUX_READY) { - quic_conn_release(qc); + if (quic_conn_release(qc)) + t = NULL; qc = NULL; } @@ -1392,12 +1393,15 @@ static inline void quic_conn_prx_cntrs_update(struct quic_conn *qc) * * This function must only be called by the thread responsible of the quic_conn * tasklet. + * + * Returns 1 if the tasklet was released, 0 otherwise */ -void quic_conn_release(struct quic_conn *qc) +int quic_conn_release(struct quic_conn *qc) { struct eb64_node *node; struct quic_rx_packet *pkt, *pktback; struct quic_conn_closed *cc_qc; + int ret = 0; TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc); @@ -1425,6 +1429,7 @@ void quic_conn_release(struct quic_conn *qc) qc->cids = NULL; pool_free(pool_head_quic_cc_buf, qc->tx.cc_buf_area); qc->tx.cc_buf_area = NULL; + ret = 1; } if (qc_test_fd(qc)) @@ -1525,6 +1530,7 @@ void quic_conn_release(struct quic_conn *qc) TRACE_PROTO("QUIC conn. freed", QUIC_EV_CONN_FREED, qc); leave: TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc); + return ret; } /* Initialize the timer task of QUIC connection.