From: Christopher Faulet Date: Tue, 14 Feb 2023 09:48:02 +0000 (+0100) Subject: BUG/MEDIUM: http-ana: Detect closed SC on opposite side during body forwarding X-Git-Tag: v2.8-dev5~197 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=af124360edda54168922d537344f9ee8dc84fa73;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: http-ana: Detect closed SC on opposite side during body forwarding During the payload forwarding, since the commit f2b02cfd9 ("MAJOR: http-ana: Review error handling during HTTP payload forwarding"), when an error occurred on one side, we don't rely anymore on a specific HTTP message state to detect it on the other side. However, nothing was added to detect the error. Thus, when this happens, a spinning loop may be experienced and an abort because of the watchdog. To fix the bug, we must detect the opposite side is closed by checking the opposite SC state. Concretly, in http_end_request() and http_end_response(), we wait for the other side iff the HTTP message state is lower to HTTP_MSG_DONE (the message is not finished) and the SC state is not SC_ST_CLO (the opposite side is not closed). In these function, we don't care if there was an error on the opposite side. We only take care to detect when we must stop waiting the other side. This patch should fix the issue #2042. No backport needed. --- diff --git a/src/http_ana.c b/src/http_ana.c index 09c374ff9c..a4092a7abb 100644 --- a/src/http_ana.c +++ b/src/http_ana.c @@ -4229,9 +4229,10 @@ static void http_end_request(struct stream *s) */ chn->flags |= CF_NEVER_WAIT; - if (txn->rsp.msg_state < HTTP_MSG_DONE) { - /* The server has not finished to respond, so we - * don't want to move in order not to upset it. + if (txn->rsp.msg_state < HTTP_MSG_DONE && s->scb->state != SC_ST_CLO) { + /* The server has not finished to respond and the + * backend SC is not closed, so we don't want to move in + * order not to upset it. */ DBG_TRACE_DEVEL("waiting end of the response", STRM_EV_HTTP_ANA, s, txn); return; @@ -4338,7 +4339,7 @@ static void http_end_response(struct stream *s) */ /* channel_dont_read(chn); */ - if (txn->req.msg_state < HTTP_MSG_DONE) { + if (txn->req.msg_state < HTTP_MSG_DONE && s->scf->state != SC_ST_CLO) { /* The client seems to still be sending data, probably * because we got an error response during an upload. * We have the choice of either breaking the connection