]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stconn: flag the stream endpoint descriptor when the app has started
authorWilly Tarreau <w@1wt.eu>
Mon, 30 Mar 2026 14:19:51 +0000 (16:19 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 30 Mar 2026 14:27:53 +0000 (16:27 +0200)
In order to improve our ability to distinguish operations that had
already started from others under high loads, it would be nice to know
if an application layer (stream) has started to work with an endpoint
or not. The use case typically is a frontend mux instantiating a stream
to instantly cancel it. Currently this info will take some time to be
detected and processed if the applcation's task takes time to wake up.
By flagging the sedesc with SE_FL_APP_STARTED the first time a the app
layer starts, the lower layers can know whether they're cancelling a
stream that has started to work or not, and act accordingly. For now
this is done unconditionally on the backend, and performed early in the
only two app layers that can be reached by a frontend: process_stream()
and process_hstream() (for haterm).

include/haproxy/stconn-t.h
src/haterm.c
src/stconn.c
src/stream.c

index 02cf9840f04f306fe917d6d81cd3c59ee0f92870..5b6d440a6bdd178deed5a31d9da16cf0681de4aa 100644 (file)
@@ -73,7 +73,9 @@ enum se_flags {
        SE_FL_DETACHED   = 0x00000010, /* The endpoint is detached (no mux/no applet) */
        SE_FL_ORPHAN     = 0x00000020, /* The endpoint is orphan (no stream connector) */
 
-        /* unused: 0x00000040 .. 0x00000080 */
+       SE_FL_APP_STARTED= 0x00000040, /* the application layer has really started */
+
+       /* unused: 0x00000080 */
 
        SE_FL_SHRD       = 0x00000100,  /* read shut, draining extra data */
        SE_FL_SHRR       = 0x00000200,  /* read shut, resetting extra data */
@@ -135,12 +137,12 @@ static forceinline char *se_show_flags(char *buf, size_t len, const char *delim,
        _(0);
        /* flags */
        _(SE_FL_T_MUX, _(SE_FL_T_APPLET, _(SE_FL_DETACHED, _(SE_FL_ORPHAN,
-       _(SE_FL_SHRD, _(SE_FL_SHRR, _(SE_FL_SHWN, _(SE_FL_SHWS,
+       _(SE_FL_APP_STARTED, _(SE_FL_SHRD, _(SE_FL_SHRR, _(SE_FL_SHWN, _(SE_FL_SHWS,
        _(SE_FL_NOT_FIRST, _(SE_FL_WEBSOCKET, _(SE_FL_EOI, _(SE_FL_EOS,
        _(SE_FL_ERROR, _(SE_FL_ERR_PENDING,  _(SE_FL_RCV_MORE,
        _(SE_FL_WANT_ROOM, _(SE_FL_EXP_NO_DATA, _(SE_FL_MAY_FASTFWD_PROD, _(SE_FL_MAY_FASTFWD_CONS,
        _(SE_FL_WAIT_FOR_HS, _(SE_FL_KILL_CONN, _(SE_FL_WAIT_DATA,
-       _(SE_FL_WONT_CONSUME, _(SE_FL_HAVE_NO_DATA, _(SE_FL_APPLET_NEED_CONN)))))))))))))))))))))))));
+       _(SE_FL_WONT_CONSUME, _(SE_FL_HAVE_NO_DATA, _(SE_FL_APPLET_NEED_CONN))))))))))))))))))))))))));
        /* epilogue */
        _(~0U);
        return buf;
index c2e112b29d37e998b65bd27d520ba6c7b1429344..2891e12b7aa92f856f151e3a035947670023f348 100644 (file)
@@ -787,6 +787,10 @@ static struct task *process_hstream(struct task *t, void *context, unsigned int
                struct htx_sl *sl = http_get_stline(htx);
                struct http_hdr_ctx expect, clength;
 
+               /* we're starting to work with this endpoint, let's flag it */
+               if (unlikely(!sc_ep_test(hs->sc, SE_FL_APP_STARTED)))
+                       sc_ep_set(hs->sc, SE_FL_APP_STARTED);
+
                if (sl->flags & HTX_SL_F_VER_11)
                        hs->ka = 5;
 
index e20c24529b3da27da0efff11c5b855a4b3dda187..6f7f3be60a8a4b0470cbf7c11bc8d8b7ec88db54 100644 (file)
@@ -210,6 +210,10 @@ struct stconn *sc_new_from_strm(struct stream *strm, unsigned int flags)
        if (unlikely(!sc))
                return NULL;
        sc->flags |= flags;
+
+       if (flags & SC_FL_ISBACK)
+               sc_ep_set(sc, SE_FL_APP_STARTED);
+
        sc_ep_set(sc, SE_FL_DETACHED);
        sc->app = &strm->obj_type;
        return sc;
@@ -227,6 +231,7 @@ struct stconn *sc_new_from_check(struct check *check)
        if (unlikely(!sc))
                return NULL;
        sc->flags = SC_FL_ISBACK;
+       sc_ep_set(sc, SE_FL_APP_STARTED);
        sc_ep_set(sc, SE_FL_DETACHED);
        sc->app = &check->obj_type;
        return sc;
index 3ba3f588806ebdc8c849c66108bb18c1703a0aef..40f9f75ae1359868dd7873b119a286a89440a23c 100644 (file)
@@ -1894,6 +1894,10 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
                                         SF_ERR_KILLED));
        }
 
+       /* we're starting to work with this endpoint, let's flag it */
+       if (unlikely(!sc_ep_test(scf, SE_FL_APP_STARTED)))
+               sc_ep_set(scf, SE_FL_APP_STARTED);
+
        /* First, attempt to receive pending data from I/O layers */
        sc_sync_recv(scf);
        sc_sync_recv(scb);