]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: flt-spoe: Properly handle end of stream from the SPOE applet
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 4 Feb 2025 17:05:33 +0000 (18:05 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 6 Feb 2025 10:19:32 +0000 (11:19 +0100)
The previous fix ("BUG/MEDIUM: applet: Don't pretend to have more data to
handle EOI/EOS/ERROR") revealed an issue with the way the SPOE applet was
reporting the end of stream, leading to never shut the applet down.

In fact, there is two bug in one. The first one is about the applet
shutdown. Since the fix above, the applet is no longer closed. Before, it
was closed because it was reported in error. But now, it is just delayed
because the applet and the SPOP stream are declared to support half close
connections. So the applet is only closed when the SPOP connection is
closed. To fix this bug, both side are now stating that half close
connections are not supported.

The second bug is about the way the end of stream is reported. It is
reported when the ACK response is received. But it is too early, because the
parent stream must process the response first. So now, we take care to have
processed the ACK from the parent applet before reporting an end of stream.

This patch must be backported with the commit above to 3.1.

src/flt_spoe.c

index 0e78d49cbd1a426b0918da07188151d8e7dcc7d0..bc1f1042bdb32a1a61eb497b8aaab6d7d43b7217 100644 (file)
@@ -391,7 +391,8 @@ static int spoe_init_appctx(struct appctx *appctx)
        applet_need_more_data(appctx);
 
        s->do_log = NULL;
-       s->scb->flags |= SC_FL_RCV_ONCE;
+       s->scb->flags |= SC_FL_RCV_ONCE | SC_FL_NOHALF;
+       s->scf->flags |= SC_FL_NOHALF;
        s->parent = spoe_appctx->spoe_ctx->strm;
 
        appctx->st0 = SPOE_APPCTX_ST_WAITING_ACK;
@@ -508,13 +509,16 @@ static void spoe_handle_appctx(struct appctx *appctx)
                        goto switchstate;
 
                case SPOE_APPCTX_ST_EXIT:
-                       appctx->st0 = SPOE_APPCTX_ST_END;
-                       applet_set_eos(appctx);
                        if (SPOE_APPCTX(appctx)->status_code != SPOP_ERR_NONE)
                                applet_set_error(appctx);
                        else
                                applet_set_eoi(appctx);
-                       __fallthrough;
+                       if (!SPOE_APPCTX(appctx)->spoe_ctx) {
+                               appctx->st0 = SPOE_APPCTX_ST_END;
+                               applet_set_eos(appctx);
+                               goto switchstate;
+                       }
+                       break;
 
                case SPOE_APPCTX_ST_END:
                        b_reset(&appctx->inbuf);