diff --git a/include/haproxy/mux_quic-t.h b/include/haproxy/mux_quic-t.h index 2dff82835..a958f4554 100644 --- a/include/haproxy/mux_quic-t.h +++ b/include/haproxy/mux_quic-t.h @@ -202,6 +202,7 @@ enum qcs_tx_st { #define QC_SF_KILL_CONN 0x00020000 // kill the whole connection with this stream #define QC_SF_FIN_STREAM 0x00040000 // FIN bit must be set for last frame of the stream +#define QC_SF_DETACH 0x00080000 /* QUIC stream descriptor, describing the stream as it appears in the QUIC_CONN, and as * it is being processed in the internal HTTP representation (HTX). diff --git a/src/mux_quic.c b/src/mux_quic.c index 578a59eeb..df6d14796 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -1564,9 +1564,16 @@ static void qc_detach(struct conn_stream *cs) struct qcc *qcc = qcs->qcc; TRACE_ENTER(QC_EV_STRM_END, qcs ? qcs->qcc->conn : NULL, qcs); + if (b_data(&qcs->tx.buf) || b_data(&qcs->tx.xprt_buf)) { + qcs->flags |= QC_SF_DETACH; + goto out; + } + qcs_destroy(qcs); if (qcc_is_dead(qcc)) qc_release(qcc); + + out: TRACE_LEAVE(QC_EV_STRM_END, qcs ? qcs->qcc->conn : NULL); } @@ -1603,7 +1610,8 @@ static struct task *qc_deferred_shut(struct task *t, void *ctx, unsigned int sta TRACE_ENTER(QC_EV_STRM_SHUT, qcc->conn, qcs); - if (qcs->flags & QC_SF_NOTIFIED) { + if (qcs->flags & QC_SF_NOTIFIED || + (b_data(&qcs->tx.buf) || b_data(&qcs->tx.xprt_buf))) { /* some data processing remains to be done first */ goto end; } diff --git a/src/xprt_quic.c b/src/xprt_quic.c index 455c83bc4..130652feb 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -1210,6 +1210,9 @@ static inline void qc_treat_acked_tx_frm(struct quic_frame *frm, eb64_insert(&qcs->tx.acked_frms, &strm->offset); } stream_acked |= qcs_try_to_consume(qcs); + + if (qcs->flags & QC_SF_DETACH) + tasklet_wakeup(qcs->shut_tl); } break; default: