]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: stconn: Block zero-copy forwarding if EOS/ERROR on consumer side
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 11 Dec 2023 12:56:15 +0000 (13:56 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 13 Dec 2023 15:45:29 +0000 (16:45 +0100)
When the producer side (h1 for now) negociates with the consumer side to
perform a zero-copy forwarding, we now consider the consumer side as blocked
if it is closed and this was reported to the SE via a end-of-stream or a
(pending) error.

It is performed before calling ->nego_ff callback function, in se_nego_ff().
This way, all consumer are concerned automatically. The aim of this patch is
to fix an issue with the QUIC mux. Indeed, it is unexpected to send a frame
on an closed stream. This triggers a BUG_ON(). Other muxes are not affected
but it remains useless to try to send data if the stream is closed.

This patch should fix the issue #2372. It must be backported to 2.9.

include/haproxy/stconn.h

index 8bddae4193fb9229fa64de7d87ffd8c54ffbc97b..9b5502a7df880bd0cca77b6195c11874122cf49c 100644 (file)
@@ -511,6 +511,16 @@ static inline size_t se_nego_ff(struct sedesc *se, struct buffer *input, size_t
 
                se->iobuf.flags &= ~IOBUF_FL_FF_BLOCKED;
                if (mux->nego_fastfwd && mux->done_fastfwd) {
+                       /* Declare SE as blocked if EOS or an error was reported.
+                        * This may happen if fast-forward was scheduled before the I/O processing on <SC>.
+                        * Wake <SC> up in this case.
+                        */
+                       if (se_fl_test(se, SE_FL_EOS|SE_FL_ERROR|SE_FL_ERR_PENDING)) {
+                               se->iobuf.flags |= IOBUF_FL_FF_BLOCKED;
+                               tasklet_wakeup(se->sc->wait_event.tasklet);
+                               goto end;
+                       }
+
                        ret = mux->nego_fastfwd(se->sc, input, count, may_splice);
                        if ((se->iobuf.flags & IOBUF_FL_FF_BLOCKED) && !(se->sc->wait_event.events & SUB_RETRY_SEND)) {
                                /* The SC must be subs for send to be notify when some