diff --git a/include/haproxy/quic_conn-t.h b/include/haproxy/quic_conn-t.h index 79f806e06..ebe3dfd21 100644 --- a/include/haproxy/quic_conn-t.h +++ b/include/haproxy/quic_conn-t.h @@ -623,9 +623,9 @@ enum qc_mux_state { #define QUIC_FL_CONN_FINALIZED (1U << 26) /* QUIC connection finalized (functional, ready to send/receive) */ #define QUIC_FL_CONN_NOTIFY_CLOSE (1U << 27) /* MUX notified about quic-conn imminent closure (idle-timeout or CONNECTION_CLOSE emission/reception) */ #define QUIC_FL_CONN_EXP_TIMER (1U << 28) /* timer has expired, quic-conn can be freed */ -#define QUIC_FL_CONN_CLOSING (1U << 29) -#define QUIC_FL_CONN_DRAINING (1U << 30) -#define QUIC_FL_CONN_IMMEDIATE_CLOSE (1U << 31) +#define QUIC_FL_CONN_CLOSING (1U << 29) /* closing state, entered on CONNECTION_CLOSE emission */ +#define QUIC_FL_CONN_DRAINING (1U << 30) /* draining state, entered on CONNECTION_CLOSE reception */ +#define QUIC_FL_CONN_IMMEDIATE_CLOSE (1U << 31) /* A CONNECTION_CLOSE must be sent */ struct quic_conn { const struct quic_version *original_version; diff --git a/src/quic_conn.c b/src/quic_conn.c index 8dd2b4846..f40ae25e6 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -3032,8 +3032,8 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt, * Rearm the idle timeout only one time when entering draining * state. */ - qc_idle_timer_do_rearm(qc); qc->flags |= QUIC_FL_CONN_DRAINING|QUIC_FL_CONN_IMMEDIATE_CLOSE; + qc_idle_timer_do_rearm(qc); qc_notify_close(qc); } break; @@ -5280,9 +5280,15 @@ static void qc_idle_timer_do_rearm(struct quic_conn *qc) { unsigned int expire; - expire = QUIC_MAX(3 * quic_pto(qc), qc->max_idle_timeout); - qc->idle_timer_task->expire = tick_add(now_ms, MS_TO_TICKS(expire)); - task_queue(qc->idle_timer_task); + if (stopping && qc->flags & (QUIC_FL_CONN_CLOSING|QUIC_FL_CONN_DRAINING)) { + TRACE_STATE("executing idle timer immediately on stopping", QUIC_EV_CONN_IDLE_TIMER, qc); + task_wakeup(qc->idle_timer_task, TASK_WOKEN_MSG); + } + else { + expire = QUIC_MAX(3 * quic_pto(qc), qc->max_idle_timeout); + qc->idle_timer_task->expire = tick_add(now_ms, MS_TO_TICKS(expire)); + task_queue(qc->idle_timer_task); + } } /* Rearm the idle timer for QUIC connection depending on boolean diff --git a/src/xprt_quic.c b/src/xprt_quic.c index 9e9258f05..2a4d01e07 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -34,6 +34,10 @@ static void quic_close(struct connection *conn, void *xprt_ctx) goto leave; } + /* Schedule a CONNECTION_CLOSE emission. If process stopping is in + * progress, quic-conn idle-timer will be scheduled immediately after + * its emission to ensure an immediate connection closing. + */ qc_check_close_on_released_mux(qc); leave: TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);