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.5-dev12~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a85c522d4;p=thirdparty%2Fhaproxy.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. --- diff --git a/src/mux_h1.c b/src/mux_h1.c index 8d2e21c748..686a7a588a 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -54,7 +54,8 @@ #define H1C_F_ST_READY 0x00002000 /* Set in ATTACHED state with a READY conn-stream. A conn-stream is not ready when * a TCP>H1 upgrade is in progress Thus this flag is only set if ATTACHED is also set */ #define H1C_F_ST_ALIVE (H1C_F_ST_IDLE|H1C_F_ST_EMBRYONIC|H1C_F_ST_ATTACHED) -/* 0x00004000 - 0x00008000 unused */ +#define H1C_F_ST_SILENT_SHUT 0x00004000 /* silent (or dirty) shutdown must be performed */ +/* 0x00008000 unused */ #define H1C_F_WANT_SPLICE 0x00010000 /* Don't read into a buffer because we want to use or we are using splicing */ #define H1C_F_ERR_PENDING 0x00020000 /* Send an error and close the connection ASAP (implies H1C_F_ST_ERROR) */ @@ -270,7 +271,7 @@ static int h1_process(struct h1c *h1c); /* h1_io_cb is exported to see it resolved in "show fd" */ struct task *h1_io_cb(struct task *t, void *ctx, unsigned int state); struct task *h1_timeout_task(struct task *t, void *context, unsigned int state); -static void h1_shutw_conn(struct connection *conn, enum cs_shw_mode mode); +static void h1_shutw_conn(struct connection *conn); static void h1_wake_stream_for_recv(struct h1s *h1s); static void h1_wake_stream_for_send(struct h1s *h1s); @@ -2697,7 +2698,7 @@ static int h1_send(struct h1c *h1c) h1_release_buf(h1c, &h1c->obuf); if (h1c->flags & H1C_F_ST_SHUTDOWN) { 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)) { @@ -3306,23 +3307,26 @@ static void h1_shutw(struct conn_stream *cs, enum cs_shw_mode mode) do_shutw: h1c->flags |= H1C_F_ST_SHUTDOWN; + if (mode != CS_SHW_NORMAL) + h1c->flags |= H1C_F_ST_SILENT_SHUT; + if (!b_data(&h1c->obuf)) - 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)); - TRACE_LEAVE(H1_EV_STRM_SHUT, conn, h1c->h1s); + conn_sock_shutw(conn, (h1c && !(h1c->flags & H1C_F_ST_SILENT_SHUT))); + TRACE_LEAVE(H1_EV_H1C_END, conn); } /* Called from the upper layer, to unsubscribe from events