From: Christopher Faulet Date: Wed, 27 Oct 2021 13:36:38 +0000 (+0200) Subject: BUG/MINOR: mux-h1: Save shutdown mode if the shutdown is delayed X-Git-Tag: v2.3.15~28 X-Git-Url: http://git.haproxy.org/?a=commitdiff_plain;h=7700441a25092c3a67a8f04926a2ed6ede1c412a;p=haproxy-2.3.git BUG/MINOR: mux-h1: Save shutdown mode if the shutdown is delayed The connection shutdown may be delayed if there are pending outgoing data. The action is performed once data are fully sent. In this case the mode (dirty/clean) was lost and a clean shutdown was always performed. Now, the mode is saved to be sure to perform the connection shutdown using the right mode. To do so, H1C_F_ST_SILENT_SHUT flag is introduced. This patch should be backported as far as 2.0. (cherry picked from commit a85c522d42f866d57cd79335a945402b81cb3948) Signed-off-by: Willy Tarreau (cherry picked from commit db451fb7d790d2675bfeda435b47a560e515b437) Signed-off-by: Christopher Faulet --- diff --git a/src/mux_h1.c b/src/mux_h1.c index fee2c0f..0948313 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -42,7 +42,10 @@ #define H1C_F_IN_ALLOC 0x00000010 /* mux is blocked on lack of input buffer */ #define H1C_F_IN_FULL 0x00000020 /* mux is blocked on input buffer full */ #define H1C_F_IN_BUSY 0x00000040 /* mux is blocked on input waiting the other side */ -/* 0x00000040 - 0x00000800 unused */ +/* 0x00000080 - 0x000002000 unused */ + +#define H1C_F_ST_SILENT_SHUT 0x00004000 /* silent (or dirty) shutdown must be performed */ +/* 0x000008000 unused */ /* Flags indicating the connection state */ #define H1C_F_CS_ERROR 0x00001000 /* connection must be closed ASAP because an error occurred */ @@ -252,7 +255,7 @@ static int h1_recv(struct h1c *h1c); static int h1_send(struct h1c *h1c); static int h1_process(struct h1c *h1c); static struct task *h1_io_cb(struct task *t, void *ctx, unsigned short state); -static void h1_shutw_conn(struct connection *conn, enum cs_shw_mode mode); +static void h1_shutw_conn(struct connection *conn); static struct task *h1_timeout_task(struct task *t, void *context, unsigned short state); static void h1_wake_stream_for_recv(struct h1s *h1s); static void h1_wake_stream_for_send(struct h1s *h1s); @@ -2255,7 +2258,7 @@ static int h1_send(struct h1c *h1c) h1_release_buf(h1c, &h1c->obuf); if (h1c->flags & H1C_F_CS_SHUTW_NOW) { TRACE_STATE("process pending shutdown for writes", H1_EV_H1C_SEND, h1c->conn); - h1_shutw_conn(conn, CS_SHW_NORMAL); + h1_shutw_conn(conn); } } else if (!(h1c->wait_event.events & SUB_RETRY_SEND)) { @@ -2699,25 +2702,27 @@ static void h1_shutw(struct conn_stream *cs, enum cs_shw_mode mode) do_shutw: h1c->flags |= H1C_F_CS_SHUTW_NOW; + if (mode != CS_SHW_NORMAL) + h1c->flags |= H1C_F_ST_SILENT_SHUT; if ((cs->flags & CS_FL_SHW) || b_data(&h1c->obuf)) goto end; - h1_shutw_conn(cs->conn, mode); + h1_shutw_conn(cs->conn); end: TRACE_LEAVE(H1_EV_STRM_SHUT, h1c->conn, h1s); } -static void h1_shutw_conn(struct connection *conn, enum cs_shw_mode mode) +static void h1_shutw_conn(struct connection *conn) { struct h1c *h1c = conn->ctx; if (conn->flags & CO_FL_SOCK_WR_SH) return; - TRACE_ENTER(H1_EV_STRM_SHUT, conn, h1c->h1s); + TRACE_ENTER(H1_EV_H1C_END, conn); conn_xprt_shutw(conn); - conn_sock_shutw(conn, (mode == CS_SHW_NORMAL)); + conn_sock_shutw(conn, (h1c && !(h1c->flags & H1C_F_ST_SILENT_SHUT))); h1c->flags = (h1c->flags & ~H1C_F_CS_SHUTW_NOW) | H1C_F_CS_SHUTDOWN; - TRACE_LEAVE(H1_EV_STRM_SHUT, conn, h1c->h1s); + TRACE_LEAVE(H1_EV_STRM_SHUT, conn); } /* Called from the upper layer, to unsubscribe from events