]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: applet: Don't pretend to have more data to handle EOI/EOS/ERROR
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 4 Feb 2025 08:20:36 +0000 (09:20 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 6 Feb 2025 10:19:32 +0000 (11:19 +0100)
The way appctx EOI/EOS/ERROR flags were reported for applets using the new
API were to state the applet had more data to deliver. But it was not
correct and for APPCTX_FL_EOS, this led to report an error on the SE because
it is not expected. More data to deliver and an end of stream is an
impossible situation.

This was added as a fix by commit b8ca114031 ("BUG/MEDIUM: applet: State
appctx have more data if its EOI/EOS/ERROR flag is set"), mainly to make the
SPOE applet work.

When an applet set one of these flags, it really means it has no more data
to deliver. So we must not try to trigger a new receive to handle these
flags. Instead we must handle them directly in task_process_applet()
function and only if the corresponding SE flags were not already set.

This patch must be backported to 3.1.

src/applet.c

index 7bd5f04603c90dbcac7944c5a12da583082358cb..4f3601ccb47cdaab94bd4ca18282cae74d12c18f 100644 (file)
@@ -921,12 +921,24 @@ struct task *task_process_applet(struct task *t, void *context, unsigned int sta
 
        TRACE_POINT(APPLET_EV_PROCESS, app);
 
-       if (b_data(&app->outbuf) || se_fl_test(app->sedesc, SE_FL_MAY_FASTFWD_PROD) ||
-           applet_fl_test(app, APPCTX_FL_EOI|APPCTX_FL_EOS|APPCTX_FL_ERROR))
+       if (b_data(&app->outbuf) || se_fl_test(app->sedesc, SE_FL_MAY_FASTFWD_PROD))
                applet_have_more_data(app);
 
        sc_applet_sync_recv(sc);
 
+       if (applet_fl_test(app, APPCTX_FL_EOI) && !se_fl_test(app->sedesc, SE_FL_EOI)) {
+               se_fl_set(app->sedesc, SE_FL_EOI);
+               TRACE_STATE("report EOI to SE", APPLET_EV_RECV|APPLET_EV_BLK, app);
+       }
+       if (applet_fl_test(app, APPCTX_FL_EOS) && !se_fl_test(app->sedesc, SE_FL_EOS)) {
+               se_fl_set(app->sedesc, SE_FL_EOS);
+               TRACE_STATE("report EOS to SE", APPLET_EV_RECV|APPLET_EV_BLK, app);
+       }
+       if (applet_fl_test(app, APPCTX_FL_ERROR) && !se_fl_test(app->sedesc, SE_FL_ERROR)) {
+               se_fl_set(app->sedesc, SE_FL_ERROR);
+               TRACE_STATE("report ERROR to SE", APPLET_EV_RECV|APPLET_EV_BLK, app);
+       }
+
        /* TODO: May be move in appctx_rcv_buf or sc_applet_process ? */
        if (sc_waiting_room(sc) && (sc->flags & SC_FL_ABRT_DONE)) {
                sc_ep_set(sc, SE_FL_EOS|SE_FL_ERROR);