]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: applet: Add notion of shutdown for write for applets
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 9 Feb 2024 14:23:21 +0000 (15:23 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 14 Feb 2024 13:22:36 +0000 (14:22 +0100)
In fact there is already flags on the SE to state a shutdown for reads or
writes was performed. But for applets, this notion does not exist. Both
flags are set in same time when the applet is released. But at the SC level,
there are functions to perform a shutdown (formely the shutw) and an abort
(formely the shutr). For applets, when a shutdown is performed on the SC, if
the applet is not immediately released, nothing is acknowledge at the SE
level.

With old way to implement applets, this was not an real issue until recently
because applets accessed to the channel/SC flags. It was thus possible to
catch the shutdowns. But the "wait" command on the CLI reveals the
flaw. Indeed, when this command is executed, nothing is read or sent. So, it
is not possible to detect the shutdowns. As a workaround, a dedicated test
on the SC flags was added at the end of the wait command I/O handler. But it
is pretty ugly.

With new way to implement applets, there is no longer access to the channel
or SC. So we must add a way to acknowledge shutdown into the SE.

This patch solves the both sides of the issue. The shutw notion is added for
applets. Its only purpose is to set SE_FL_SHWN flags. This flag is tested by
all applets, so, it solves the issue quite simply.

Note that it is described as a bug fix but there is no real issue, just a
design flaw. However, if the "wait" command is backported, this patch must
be backported too. Unfortinately it will require an adaptation because there
is no appctx flags on older versions.

include/haproxy/applet.h
src/applet.c
src/stconn.c

index 17222c5244c05b3c10d112e0d15128768ffedcfc..22c68fbd981654976454ee6968528e5586aab083 100644 (file)
@@ -132,6 +132,14 @@ static inline void __appctx_free(struct appctx *appctx)
        _HA_ATOMIC_DEC(&nb_applets);
 }
 
+static inline void appctx_shutw(struct appctx *appctx)
+{
+       if (se_fl_test(appctx->sedesc, SE_FL_SHW))
+               return;
+
+       se_fl_set(appctx->sedesc, SE_FL_SHWN);
+}
+
 /* wakes up an applet when conditions have changed. We're using a macro here in
  * order to retrieve the caller's place.
  */
index 275e4e65c7dff1bf77073c5299f6a006a9a12197..4fc4e4018a749047b3774eadaccf376cfc49924a 100644 (file)
@@ -395,7 +395,7 @@ void applet_reset_svcctx(struct appctx *appctx)
  */
 void appctx_shut(struct appctx *appctx)
 {
-       if (se_fl_test(appctx->sedesc, SE_FL_SHR | SE_FL_SHW))
+       if (applet_fl_test(appctx, APPCTX_FL_SHUTDOWN))
                return;
 
        TRACE_ENTER(APPLET_EV_RELEASE, appctx);
index 70f27db81670c5f6dd3b3c51117a18d6f893ef30..9951c80f42dddd10ccfd8d714e92aa0b49dd7f08 100644 (file)
@@ -917,6 +917,8 @@ static void sc_app_shut_applet(struct stconn *sc)
        switch (sc->state) {
        case SC_ST_RDY:
        case SC_ST_EST:
+               appctx_shutw(__sc_appctx(sc));
+
                /* we have to shut before closing, otherwise some short messages
                 * may never leave the system, especially when there are remaining
                 * unread data in the socket input buffer, or when nolinger is set.