]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: mux-quic: adjust wakeup behavior
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 3 Jun 2025 15:18:30 +0000 (17:18 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 12 Jun 2025 09:12:49 +0000 (11:12 +0200)
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.

src/mux_quic.c

index 9343f8d10e087acf2c686bd48460739c87d92c07..ae38867d4ee13ebe20fd0c5248691e31ec2636b8 100644 (file)
@@ -3114,10 +3114,10 @@ static void qcc_shutdown(struct qcc *qcc)
        TRACE_LEAVE(QMUX_EV_QCC_END, qcc->conn);
 }
 
-/* Loop through all qcs from <qcc>. Report error on stream endpoint if
- * connection on error and wake them.
+/* Loop through all qcs from <qcc> 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 <qcc> 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);