]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: cli/streams: make "show sess" dump all streams till the new epoch
authorWilly Tarreau <w@1wt.eu>
Wed, 24 Feb 2021 10:53:17 +0000 (11:53 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 24 Feb 2021 11:12:51 +0000 (12:12 +0100)
Instead of placing the current stream at the end of the stream list when
issuing a "show sess" on the CLI as was done in 2.2 with commit c6e7a1b8e
("MINOR: cli: make "show sess" stop at the last known session"), now we
compare the listed stream's epoch with the dumping stream's and stop on
more recent ones.

This way we're certain to always only dump known streams at the moment we
issue the dump command without having to modify the list. In theory we
could miss some streams if more than 2^31 "show sess" requests are issued
while an old stream remains present, but that's 68 years at 1 "show sess"
per second and it's unlikely we'll keep a process, let alone a stream, that
long.

It could be verified that the count of dumped streams still matches the
one before this change.

src/stream.c

index 0b86488a53675e579060a75865fb0050c8095901..d04581a335921ecc66732d5396623a44beecbb69 100644 (file)
@@ -3192,16 +3192,6 @@ static int cli_parse_show_sess(char **args, char *payload, struct appctx *appctx
         * it so that we know which streams were already there before us.
         */
        si_strm(appctx->owner)->stream_epoch = _HA_ATOMIC_XADD(&stream_epoch, 1);
-
-       /* we need to put an end marker into the streams list. We're just moving
-        * ourselves there, so that once we found ourselves we know we've reached
-        * the end. Without this we can run forever if new streams arrive faster
-        * than we can dump them.
-        */
-       HA_SPIN_LOCK(STRMS_LOCK, &streams_lock);
-       LIST_DEL(&si_strm(appctx->owner)->list);
-       LIST_ADDQ(&streams, &si_strm(appctx->owner)->list);
-       HA_SPIN_UNLOCK(STRMS_LOCK, &streams_lock);
        return 0;
 }
 
@@ -3253,13 +3243,17 @@ static int cli_io_handler_dump_sess(struct appctx *appctx)
                        LIST_INIT(&appctx->ctx.sess.bref.users);
                }
 
-               /* and start from where we stopped, never going further than ourselves */
-               while (appctx->ctx.sess.bref.ref != si_strm(appctx->owner)->list.n) {
+               /* and start from where we stopped */
+               while (appctx->ctx.sess.bref.ref != &streams) {
                        char pn[INET6_ADDRSTRLEN];
                        struct stream *curr_strm;
 
                        curr_strm = LIST_ELEM(appctx->ctx.sess.bref.ref, struct stream *, list);
 
+                       /* check if we've found a stream created after issuing the "show sess" */
+                       if ((int)(curr_strm->stream_epoch - si_strm(appctx->owner)->stream_epoch) > 0)
+                               break;
+
                        if (appctx->ctx.sess.target) {
                                if (appctx->ctx.sess.target != (void *)-1 && appctx->ctx.sess.target != curr_strm)
                                        goto next_sess;