]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: cli: make "show sess" stop at the last known session
authorWilly Tarreau <w@1wt.eu>
Sat, 27 Jun 2020 23:24:12 +0000 (01:24 +0200)
committerWilly Tarreau <w@1wt.eu>
Sat, 27 Jun 2020 23:41:56 +0000 (01:41 +0200)
"show sess" and particularly "show sess all" can be very slow when dumping
lots of information, and while dumping, new sessions might appear, making
the output really endless. When threads are used, this causes a double
problem:
  - all threads are paused during the dump, so an overly long dump degrades
    the quality of service ;

  - since all threads are paused, more events get postponed, possibly
    resulting in more streams to be dumped on next invocation of the dump
    function.

This patch addresses this long-lasting issue by doing something simple:
the CLI's stream is moved at the end of the steams list, serving as an
identifiable marker to end the dump, because all entries past it were
added after the command was entered. As a result, the CLI's stream always
appears as the last one.

It may make sense to backport this to stable branches where dumping live
streams is difficult as well.

doc/management.txt
src/stream.c

index 00ce3909ea846f728b9c9b8e5f91156d43505e58..0877992b6f4809e017520d3305568395cdf1e675 100644 (file)
@@ -2390,7 +2390,11 @@ show servers state [<backend>]
 show sess
   Dump all known sessions. Avoid doing this on slow connections as this can
   be huge. This command is restricted and can only be issued on sockets
-  configured for levels "operator" or "admin".
+  configured for levels "operator" or "admin". Note that on machines with
+  quickly recycled connections, it is possible that this output reports less
+  entries than really exist because it will dump all existing sessions up to
+  the last one that was created before the command was entered; those which
+  die in the mean time will not appear.
 
 show sess <id>
   Display a lot of internal information about the specified session identifier.
index f0618de4d0e3a903cfc4cc7b5deda7ffef68e67a..287f40647c1faa256ab96e46d6bdb966fec7b4c4 100644 (file)
@@ -3137,6 +3137,15 @@ static int cli_parse_show_sess(char **args, char *payload, struct appctx *appctx
        appctx->ctx.sess.section = 0; /* start with stream status */
        appctx->ctx.sess.pos = 0;
 
+       /* 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;
 }
 
@@ -3188,8 +3197,8 @@ static int cli_io_handler_dump_sess(struct appctx *appctx)
                        LIST_INIT(&appctx->ctx.sess.bref.users);
                }
 
-               /* and start from where we stopped */
-               while (appctx->ctx.sess.bref.ref != &streams) {
+               /* and start from where we stopped, never going further than ourselves */
+               while (appctx->ctx.sess.bref.ref != si_strm(appctx->owner)->list.n) {
                        char pn[INET6_ADDRSTRLEN];
                        struct stream *curr_strm;