From: Christopher Faulet Date: Tue, 22 Nov 2022 16:16:22 +0000 (+0100) Subject: BUG/MEDIUM: mux-h1: Subscribe for reads on error on sending path X-Git-Tag: v2.7-dev10~24 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a462ee0af4fa5e3172897edcfc532a5c4991dafa;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: mux-h1: Subscribe for reads on error on sending path The recent refactoring about errors handling in the H1 multiplexer introduced a bug on abort when the client wait for the server response. The bug only exists if abortonclose option is not enabled. Indeed, in this case, when the end of the message is reached, the mux stops to receive data because these data are part of the next request. However, error on the sending path are no longer fatal. An error on the reading path must be caught to do so. So, in case of a client abort, the error is not reported to the upper layer and the H1 connection cannot be closed if some pending data are blocked (remember, an error on sending path was detected, blocking outgoing data). To be sure to have a chance to detect the abort in the case, when an error is detected on the sending path, we force the subscription for reads. This patch, with the previous one, should fix the issue #1943. It is 2.7-specific, no backport is needed. --- diff --git a/src/mux_h1.c b/src/mux_h1.c index 2cfe17694e..b730364ac5 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -2890,6 +2890,13 @@ static int h1_send(struct h1c *h1c) h1c->flags |= H1C_F_ERR_PENDING; if (h1c->flags & H1C_F_EOS) h1c->flags |= H1C_F_ERROR; + else if (!(h1c->wait_event.events & SUB_RETRY_RECV)) { + /* EOS not seen, so subscribe for reads to be able to + * catch the error on the reading path. It is especially + * important if EOI was reached. + */ + h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event); + } b_reset(&h1c->obuf); } @@ -3846,6 +3853,13 @@ static int h1_snd_pipe(struct stconn *sc, struct pipe *pipe) h1c->flags = (h1c->flags & ~H1C_F_WANT_SPLICE) | H1C_F_ERR_PENDING; if (h1c->flags & H1C_F_EOS) h1c->flags |= H1C_F_ERROR; + else if (!(h1c->wait_event.events & SUB_RETRY_RECV)) { + /* EOS not seen, so subscribe for reads to be able to + * catch the error on the reading path. It is especially + * important if EOI was reached. + */ + h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event); + } se_fl_set_error(h1s->sd); TRACE_DEVEL("connection error", H1_EV_STRM_ERR|H1_EV_H1C_ERR|H1_EV_H1S_ERR, h1c->conn, h1s); }