From: Amaury Denoyelle Date: Fri, 8 Oct 2021 15:57:41 +0000 (+0200) Subject: MEDIUM: mux-quic: defer stream shut if remaining tx data X-Git-Tag: v2.5-dev10~57 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cae07919422afa4f865fe325b1248ce26aa8d8c6;p=thirdparty%2Fhaproxy.git MEDIUM: mux-quic: defer stream shut if remaining tx data Defer the shutting of a qcs if there is still data in its tx buffers. In this case, the conn_stream is closed but the qcs is kept with a new flag QC_SF_DETACH. On ACK reception, the xprt wake up the shut_tl tasklet if the stream is flagged with QC_SF_DETACH. This tasklet is responsible to free the qcs and possibly the qcc when all bidirectional streams are removed. --- diff --git a/include/haproxy/mux_quic-t.h b/include/haproxy/mux_quic-t.h index 2dff82835c..a958f45542 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 578a59eebd..df6d147960 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 455c83bc40..130652feb5 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: