]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: stconn/stream: Forward shutdown on write timeout
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 6 Sep 2023 06:59:33 +0000 (08:59 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 6 Sep 2023 07:29:27 +0000 (09:29 +0200)
The commit 7f59d68fe2 ("BUG/MEDIIM: stconn: Flush output data before
forwarding close to write side") introduced a regression. When a write
timeout is detected, the shutdown is no longer forwarded. Dependig on the
channels state, it may block the processing, waiting the client or the
server leaves.

The commit above tries to avoid to truncate messages on shutdown but on
write timeout, if the channel is not empty, there is nothing more we can do
to send these data. It means the endpoint is unable to send data. In this
case, we must forward the shutdown.

This patch should be backported as far as 2.2.

src/stconn.c
src/stream.c

index 27544645c4b80b771f999ff3c9c62185ad0e3a33..273a1d894e36905ecbfa3ab2b94b53d07af36889 100644 (file)
@@ -512,6 +512,10 @@ struct appctx *sc_applet_create(struct stconn *sc, struct applet *app)
  */
 static inline int sc_cond_forward_shut(struct stconn *sc)
 {
+       /* Foward the shutdown if an write error occurred on the input channel */
+       if (sc_ic(sc)->flags & CF_WRITE_TIMEOUT)
+               return 1;
+
        /* The close must not be forwarded */
        if (!(sc->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) || !(sc->flags & SC_FL_NOHALF))
                return 0;
index 00a6c07b7826dc707cbd87237d4ee69256434f8a..45b0c56d9849cdfb0f3dbcf05f1a2e4433960b72 100644 (file)
@@ -2378,7 +2378,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
 
        /* shutdown(write) pending */
        if (unlikely((scb->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) == SC_FL_SHUT_WANTED &&
-                    channel_is_empty(req))) {
+                    (channel_is_empty(req) || (req->flags & CF_WRITE_TIMEOUT)))) {
                if (scf->flags & SC_FL_ERROR)
                        scb->flags |= SC_FL_NOLINGER;
                sc_shutdown(scb);
@@ -2502,7 +2502,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
 
        /* shutdown(write) pending */
        if (unlikely((scf->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) == SC_FL_SHUT_WANTED &&
-                    channel_is_empty(res))) {
+                    (channel_is_empty(res) || (res->flags & CF_WRITE_TIMEOUT)))) {
                sc_shutdown(scf);
        }