]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: stream: Forward shutdowns when unhandled errors are caught
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 10 May 2023 14:28:38 +0000 (16:28 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 10 May 2023 14:45:36 +0000 (16:45 +0200)
In process_stream(), after request and response analyzers evaluation,
unhandled errors are processed, if any. In this case, depending on the case,
remaining request or response analyzers may be removed, unlesse the last one
about end of filters. However, auto-close is not reenabled in same
time. Thus it is possible to not forward the shutdown for a side to the
other one while no analyzer is there to do so or at least to make evolved
the situation.

In theory, it is thus possible to freeze a stream if no wakeup happens. And
it seems possible because it explain a freeze we've oberseved.

This patch could be backported to every stable versions but only after a
period of observation and if it may match an unexplained bug. It should not
lead to any loop but at worst and eventually to truncated messages.

src/stream.c

index 36f8eeb97f356a17c1a2153f6f18920f68f40bad..8505aefd520e9b3ad65b0b7168263847bb466c17 100644 (file)
@@ -2143,6 +2143,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
                if ((scf->flags & SC_FL_ERROR) || req->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT)) {
                        /* Report it if the client got an error or a read timeout expired */
                        req->analysers &= AN_REQ_FLT_END;
+                       channel_auto_close(req);
                        if (scf->flags & SC_FL_ERROR) {
                                _HA_ATOMIC_INC(&s->be->be_counters.cli_aborts);
                                _HA_ATOMIC_INC(&sess->fe->fe_counters.cli_aborts);
@@ -2188,6 +2189,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
                else if ((scb->flags & SC_FL_ERROR) || res->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT)) {
                        /* Report it if the server got an error or a read timeout expired */
                        res->analysers &= AN_RES_FLT_END;
+                       channel_auto_close(res);
                        if (scb->flags & SC_FL_ERROR) {
                                _HA_ATOMIC_INC(&s->be->be_counters.srv_aborts);
                                _HA_ATOMIC_INC(&sess->fe->fe_counters.srv_aborts);