From: Amaury Denoyelle Date: Tue, 3 Jun 2025 15:18:30 +0000 (+0200) Subject: BUG/MEDIUM: mux-quic: adjust wakeup behavior X-Git-Tag: v3.3-dev2~74 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=044ad3a602d7b217ec1470f06ec15bca102ff685;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: mux-quic: adjust wakeup behavior Change wake callback behavior for QUIC MUX. This operation loops over each QCS and notify their stream data layer on certain events via internal helper qcc_wake_some_streams(). Previously, streams were notified only if an error occured on the connection. Change this to notify streams data layer everytime wake callback is used. This behavior is now identical to H2 MUX. qcc_wake_some_streams() is also renamed to qcc_wake_streams(), as it better reflect its true behavior. This change should not have performance impact as wake mux ops should not be called frequently. Note that qcc_wake_streams() can also be called directly via qcc_io_process() to ensure a new error is correctly propagated. As wake callback first uses qcc_io_process(), it will only call qcc_wake_streams() if no error is present. No known issue is associated with this commit. However, it could prevent freezing transfer under certain condition. As such, it is considered as a bug fix worthy of backporting. This should be backported after a period of observation. --- diff --git a/src/mux_quic.c b/src/mux_quic.c index 9343f8d10..ae38867d4 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -3114,10 +3114,10 @@ static void qcc_shutdown(struct qcc *qcc) TRACE_LEAVE(QMUX_EV_QCC_END, qcc->conn); } -/* Loop through all qcs from . Report error on stream endpoint if - * connection on error and wake them. +/* Loop through all qcs from and wake their associated data layer if + * still active. Also report error on it if connection is already in error. */ -static int qcc_wake_some_streams(struct qcc *qcc) +static void qcc_wake_streams(struct qcc *qcc) { struct qcs *qcs; struct eb64_node *node; @@ -3134,11 +3134,10 @@ static int qcc_wake_some_streams(struct qcc *qcc) if (qcc->flags & (QC_CF_ERR_CONN|QC_CF_ERRL)) { TRACE_POINT(QMUX_EV_QCC_WAKE, qcc->conn, qcs); se_fl_set_error(qcs->sd); - qcs_alert(qcs); } - } - return 0; + qcs_alert(qcs); + } } /* Conduct operations which should be made for connection after @@ -3193,7 +3192,7 @@ static int qcc_io_process(struct qcc *qcc) /* Report error if set on stream endpoint layer. */ if (qcc->flags & (QC_CF_ERR_CONN|QC_CF_ERRL)) - qcc_wake_some_streams(qcc); + qcc_wake_streams(qcc); out: if (qcc_is_dead(qcc)) @@ -3942,7 +3941,11 @@ static int qmux_wake(struct connection *conn) goto release; } - qcc_wake_some_streams(qcc); + /* Wake all streams, unless an error is set as qcc_io_process() has + * already woken them in this case. + */ + if (!(qcc->flags & (QC_CF_ERR_CONN|QC_CF_ERRL))) + qcc_wake_streams(qcc); qcc_refresh_timeout(qcc);