From: Christopher Faulet Date: Thu, 11 Jul 2019 13:40:25 +0000 (+0200) Subject: BUG/MEDIUM: mux-h1: Don't release h1 connection if there is still data to send X-Git-Tag: v2.1-dev1~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=37243bc61f9c5cf88d1fe96a016e5f2f7e5e0c60;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: mux-h1: Don't release h1 connection if there is still data to send 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. --- diff --git a/src/mux_h1.c b/src/mux_h1.c index 8712d2a0f8..c8db2637b9 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -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);