BUG/MEDIUM: mux-h2: fix the conditions to end the h2_send() loop

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.
This commit is contained in:
Willy Tarreau 2019-05-29 17:36:37 +02:00
parent 58d87f31f7
commit 7f1265a238

View 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;
}