]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: mux-h1: Don't release h1 connection if there is still data to send
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 11 Jul 2019 13:40:25 +0000 (15:40 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 12 Jul 2019 08:06:41 +0000 (10:06 +0200)
When the h1 stream (h1s) is detached, If the connection is not really shutdown
yet and if there is still some data to send, the h1 connection (h1c) must not be
released. Otherwise, the remaining data are lost. This bug was introduced by the
commit 3ac0f430 ("BUG/MEDIUM: mux-h1: Always release H1C if a shutdown for
writes was reported").

Here is the conditions to release an h1 connection when the h1 stream is
detached :

  * An error or a shutdown write occurred on the connection
    (CO_FL_ERROR|CO_FL_SOCK_WR_SH)

  * an error, an h2 upgrade or full shutdown occurred on the h1 connection
    (H1C_F_CS_ERROR||H1C_F_UPG_H2C|H1C_F_CS_SHUTDOWN)

  * A shutdown write is pending on the h1 connection and there is no more data
    in the output buffer
    ((h1c->flags & H1C_F_CS_SHUTW_NOW) && !b_data(&h1c->obuf))

If one of these conditions is fulfilled, the h1 connection is
released. Otherwise, the release is delayed. If we are waiting to send remaining
data, a timeout is set.

This patch must be backported to 2.0 and 1.9. It fixes the issue #164.

src/mux_h1.c

index 8712d2a0f8c0f7d9ff775f99af8d9804de44de7a..c8db2637b91fbbb1e0c37ae1dfed24bf39cb9529 100644 (file)
@@ -1978,7 +1978,7 @@ static int h1_process(struct h1c * h1c)
        }
 
        if (!h1s) {
-               if (h1c->flags & H1C_F_CS_ERROR   ||
+               if (h1c->flags & (H1C_F_CS_ERROR|H1C_F_CS_SHUTDOWN) ||
                    conn->flags & (CO_FL_ERROR | CO_FL_SOCK_WR_SH) ||
                    conn_xprt_read0_pending(conn))
                        goto release;
@@ -2213,8 +2213,10 @@ static void h1_detach(struct conn_stream *cs)
        }
 
        /* We don't want to close right now unless the connection is in error or shut down for writes */
-       if ((h1c->flags & (H1C_F_CS_ERROR|H1C_F_CS_SHUTW_NOW|H1C_F_CS_SHUTDOWN|H1C_F_UPG_H2C)) ||
-           (h1c->conn->flags & (CO_FL_ERROR|CO_FL_SOCK_WR_SH)) || !h1c->conn->owner)
+       if ((h1c->flags & (H1C_F_CS_ERROR|H1C_F_CS_SHUTDOWN|H1C_F_UPG_H2C)) ||
+           (h1c->conn->flags & (CO_FL_ERROR|CO_FL_SOCK_WR_SH)) ||
+           ((h1c->flags & H1C_F_CS_SHUTW_NOW) && !b_data(&h1c->obuf)) ||
+           !h1c->conn->owner)
                h1_release(h1c);
        else {
                tasklet_wakeup(h1c->wait_event.tasklet);