]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: mux-quic: fix EOI for request without payload
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 12 May 2023 16:16:31 +0000 (18:16 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 16 May 2023 15:53:45 +0000 (17:53 +0200)
When a full message is received for a stream, MUX is responsible to set
EOI flag. This was done through rcv_buf stream callback by checking if
QCS HTX buffer contained the EOM flag.

This is not correct for HTTP without body. In this case, QCS HTX buffer
is never used. Only a local HTX buffer is used to transfer headers just
as stream endpoint is created. As such, EOI is never transmitted to the
upper layer.

If the transfer occur without any issue, this does not seem to cause any
problem. However, in case the transfer is aborted, the stream is never
released which cause a memory leak and prevent the process soft-stop.

To fix this, also check if EOM is put by application layer during
headers conversion. If true, this is transferred through a new argument
to qc_attach_sc() MUX function which is responsible to set the EOI flag.

This issue was reproduced using h2load with hundred of connections.
h2load is interrupted with a SIGINT which causes streams to never be
closed on haproxy side.

This should be backported up to 2.6.

src/h3.c
src/hq_interop.c
src/mux_quic.c

index 50e6b4f81c9a9b90bef4926f307b960dcc400fd4..59e57c2bf5bdc3ffbd63e4fbd084c5e6e9a8ebf5 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -680,7 +680,7 @@ static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
        htx_to_buf(htx, &htx_buf);
        htx = NULL;
 
-       if (!qc_attach_sc(qcs, &htx_buf)) {
+       if (!qc_attach_sc(qcs, &htx_buf, fin)) {
                h3c->err = H3_INTERNAL_ERROR;
                len = -1;
                goto out;
index cbbf47288a71450b2d413b4c92a00615158770be..f34657854bc03a740b2ee862170b0fb08f6d3f2e 100644 (file)
@@ -88,7 +88,7 @@ static ssize_t hq_interop_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
        htx_add_endof(htx, HTX_BLK_EOH);
        htx_to_buf(htx, &htx_buf);
 
-       if (!qc_attach_sc(qcs, &htx_buf))
+       if (!qc_attach_sc(qcs, &htx_buf, fin))
                return -1;
 
        b_free(&htx_buf);
index 3cc24108d146229c1c26119741a7b2e6517e0f27..c4b695754f0dfc4027c0788efa7bd178ec6c0378 100644 (file)
@@ -639,7 +639,7 @@ static struct qcs *qcc_init_stream_remote(struct qcc *qcc, uint64_t id)
        return NULL;
 }
 
-struct stconn *qc_attach_sc(struct qcs *qcs, struct buffer *buf)
+struct stconn *qc_attach_sc(struct qcs *qcs, struct buffer *buf, char fin)
 {
        struct qcc *qcc = qcs->qcc;
        struct session *sess = qcc->conn->owner;
@@ -679,6 +679,11 @@ struct stconn *qc_attach_sc(struct qcs *qcs, struct buffer *buf)
        BUG_ON_HOT(!LIST_INLIST(&qcs->el_opening));
        LIST_DEL_INIT(&qcs->el_opening);
 
+       if (fin) {
+               TRACE_STATE("report end-of-input", QMUX_EV_STRM_RECV, qcc->conn, qcs);
+               se_fl_set(qcs->sd, SE_FL_EOI);
+       }
+
        return qcs->sd->sc;
 }
 
@@ -2717,7 +2722,7 @@ static size_t qc_recv_buf(struct stconn *sc, struct buffer *buf,
        else {
                se_fl_clr(qcs->sd, SE_FL_RCV_MORE | SE_FL_WANT_ROOM);
 
-               /* Set end-of-input if FIN received and all data extracted. */
+               /* Set end-of-input when full message properly received. */
                if (fin) {
                        TRACE_STATE("report end-of-input", QMUX_EV_STRM_RECV, qcc->conn, qcs);
                        se_fl_set(qcs->sd, SE_FL_EOI);