BUG/MEDIUM: mux-h1: Disable the splicing when nothing is received
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 24 Jul 2020 14:13:12 +0000 (16:13 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 24 Jul 2020 16:31:31 +0000 (18:31 +0200)
When nothing is received when xprt->rcv_pipe() is called, and if the pipe is
empty, the mux rcv_buf() callback is called. Because the splicing is enabled,
nothing is performed and the H1 connection is woken up. Unfortunately, the H1
connection will do the same with the H1 stream. Thus, while nothing is received,
a ping-pong loop between the H1 connection and a H1 stream will consume all the
CPU. To avoid this loop, the splicing is disabled in this case. This way, the H1
connection will try to read data and it will wake up the H1 stream only if it
reads something.

This bug was previously fixed by the commit a1dde23 ("BUG/MEDIUM: mux-h1:
Subscribe rather than waking up in h1_rcv_buf()"). But it was reverted because
it relies on not-backported changes on the connection layer.

This patch must be backported to 2.0.

src/mux_h1.c

index 0fe0475..cac6e08 100644 (file)
@@ -2735,7 +2735,11 @@ static int h1_rcv_pipe(struct conn_stream *cs, struct pipe *pipe, unsigned int c
        if (h1m->state == H1_MSG_DATA && count > h1m->curr_len)
                count = h1m->curr_len;
        ret = cs->conn->xprt->rcv_pipe(cs->conn, cs->conn->xprt_ctx, pipe, count);
-       if (h1m->state == H1_MSG_DATA && ret >= 0) {
+       if (ret <= 0) {
+               h1s->flags &= ~(H1S_F_BUF_FLUSH|H1S_F_SPLICED_DATA);
+               TRACE_STATE("disable splicing on !ret", H1_EV_STRM_RECV, cs->conn, h1s);
+       }
+       else if (h1m->state == H1_MSG_DATA) {
                h1m->curr_len -= ret;
                if (!h1m->curr_len) {
                        h1s->flags &= ~(H1S_F_BUF_FLUSH|H1S_F_SPLICED_DATA);