]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: mux-h2: fix the conditions to end the h2_send() loop
authorWilly Tarreau <w@1wt.eu>
Wed, 29 May 2019 15:36:37 +0000 (17:36 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 29 May 2019 15:54:35 +0000 (17:54 +0200)
The test for the mux alloc failure in h2_send() right after an attempt
at h2_process_mux() used to make sense as it tried to detect that this
latter failed to produce data. But now that we have a list of buffers,
it is a perfectly valid situation where there can still be data in the
buffer(s).

So now when we see this flag we only declare it's the last run on the
loop. In addition we need to make sure we break out of the loop on
snd_buf failure, or we'll loop indefinitely, for example when the buf
is full and we can't send.

No backport is needed.

src/mux_h2.c

index 557a158cab68b52d6853e17627f1873fa22500b3..c5a10dfce126622832977456202d2c370a87469c 100644 (file)
@@ -2825,7 +2825,7 @@ static int h2_send(struct h2c *h2c)
                        done = h2_process_mux(h2c);
 
                if (h2c->flags & H2_CF_MUX_MALLOC)
-                       break;
+                       done = 1; // we won't go further without extra buffers
 
                if (conn->flags & CO_FL_ERROR)
                        break;
@@ -2836,12 +2836,16 @@ static int h2_send(struct h2c *h2c)
                for (buf = br_head(h2c->mbuf); b_size(buf); buf = br_del_head(h2c->mbuf)) {
                        if (b_data(buf)) {
                                int ret = conn->xprt->snd_buf(conn, conn->xprt_ctx, buf, b_data(buf), flags);
-                               if (!ret)
+                               if (!ret) {
+                                       done = 1;
                                        break;
+                               }
                                sent = 1;
                                b_del(buf, ret);
-                               if (b_data(buf))
+                               if (b_data(buf)) {
+                                       done = 1;
                                        break;
+                               }
                        }
                        b_free(buf);
                        released++;
@@ -2888,8 +2892,9 @@ static int h2_send(struct h2c *h2c)
        if (!br_data(h2c->mbuf))
                return sent;
 schedule:
-       if (!(h2c->wait_event.events & SUB_RETRY_SEND))
+       if (!(conn->flags & CO_FL_ERROR) && !(h2c->wait_event.events & SUB_RETRY_SEND))
                conn->xprt->subscribe(conn, conn->xprt_ctx, SUB_RETRY_SEND, &h2c->wait_event);
+
        return sent;
 }