]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: mux-pt/mux-h1: Release the pipe on connection error on sending path
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 30 Jul 2024 06:41:03 +0000 (08:41 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Tue, 30 Jul 2024 07:05:25 +0000 (09:05 +0200)
When data are sent using the kernel splicing, if a connection error
occurred, the pipe must be released. Indeed, in that case, no more data can
be sent and there is no reason to not release the pipe. But it is in fact an
issue for the stream because the channel will appear are not empty. This may
prevent the stream to be released. This happens on 2.8 when a filter is also
attached on it. On 2.9 and upper, it seems there is not issue. But it is
hard to be sure and the current patch remains valid is all cases. On 2.6 and
lower, the code is not the same and, AFAIK, there is no issue.

This patch must be backported to 2.8. However, on 2.8, there is no zero-copy
data forwarding. The patch must be adapted. There is no done_ff/resume_ff
callback functions for muxes. The pipe must released in sc_conn_send() when
an error flag is set on the SE, after the call to snd_pipe callback
function.

src/mux_h1.c
src/mux_pt.c

index f6254338f7e6fc40ef4fef4b5ed96307de10718c..89bcc3c81efe1857bcc2811e72eebd41dcbe423d 100644 (file)
@@ -4819,6 +4819,10 @@ static size_t h1_done_ff(struct stconn *sc)
                        h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event);
                }
                se_fl_set_error(h1s->sd);
+               if (sd->iobuf.pipe) {
+                       put_pipe(sd->iobuf.pipe);
+                       sd->iobuf.pipe = NULL;
+               }
                TRACE_DEVEL("connection error", H1_EV_STRM_ERR|H1_EV_H1C_ERR|H1_EV_H1S_ERR, h1c->conn, h1s);
        }
 
@@ -5074,6 +5078,10 @@ static int h1_resume_fastfwd(struct stconn *sc, unsigned int flags)
                        h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event);
                }
                se_fl_set_error(h1s->sd);
+               if (h1s->sd->iobuf.pipe) {
+                       put_pipe(h1s->sd->iobuf.pipe);
+                       h1s->sd->iobuf.pipe = NULL;
+               }
                TRACE_DEVEL("connection error", H1_EV_STRM_ERR|H1_EV_H1C_ERR|H1_EV_H1S_ERR, h1c->conn, h1s);
        }
 
index 46e1d2e94e6cdd1a8ef47a3a1e877cf92818af9a..e0d31bb7bea0bb334ce71f3956381cfe7f1f7217 100644 (file)
@@ -621,6 +621,10 @@ static size_t mux_pt_done_ff(struct stconn *sc)
                if (conn_xprt_read0_pending(conn))
                        se_fl_set(ctx->sd, SE_FL_EOS);
                se_fl_set_error(ctx->sd);
+               if (se->iobuf.pipe) {
+                       put_pipe(se->iobuf.pipe);
+                       se->iobuf.pipe = NULL;
+               }
                TRACE_DEVEL("error on connection", PT_EV_TX_DATA|PT_EV_CONN_ERR, conn, sc);
        }
 
@@ -736,6 +740,10 @@ static int mux_pt_resume_fastfwd(struct stconn *sc, unsigned int flags)
                if (conn_xprt_read0_pending(conn))
                        se_fl_set(ctx->sd, SE_FL_EOS);
                se_fl_set_error(ctx->sd);
+               if (se->iobuf.pipe) {
+                       put_pipe(se->iobuf.pipe);
+                       se->iobuf.pipe = NULL;
+               }
                TRACE_DEVEL("error on connection", PT_EV_TX_DATA|PT_EV_CONN_ERR, conn, sc);
        }