From a462ee0af4fa5e3172897edcfc532a5c4991dafa Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Tue, 22 Nov 2022 17:16:22 +0100 Subject: [PATCH] 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. --- src/mux_h1.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/mux_h1.c b/src/mux_h1.c index 2cfe17694..b730364ac 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); }