]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: http-ana: Detect closed SC on opposite side during body forwarding
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 14 Feb 2023 09:48:02 +0000 (10:48 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 17 Feb 2023 09:16:25 +0000 (10:16 +0100)
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.

src/http_ana.c

index 09c374ff9c2373a3541f6e1360225d58b3ad16ed..a4092a7abba459f33106a4b4c0ab7acde9c8df6d 100644 (file)
@@ -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