]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: cli/fd: don't isolate the thread for each individual fd
authorWilly Tarreau <w@1wt.eu>
Tue, 18 Dec 2018 14:45:11 +0000 (15:45 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 18 Dec 2018 14:45:11 +0000 (15:45 +0100)
It takes ages to proceed with "show fd" when there is sustained activity
because it uses the rendez-vous point for each and every file descriptor
in the loop. It's very common to see socat timeout there.

Instead of doing this, let's just isolate the function when entering the
loop. Its duration is limited by the number of FDs that may be emitted in
a single buffer anyway, so it's much lighter and responds much faster.

src/cli.c

index 23caac3b7758fad5fa4e3947a3af95719b6a2807..ae419b039912f3fbc6bc94ab4e03a5dc59762d07 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -865,12 +865,18 @@ static int cli_io_handler_show_fd(struct appctx *appctx)
 {
        struct stream_interface *si = appctx->owner;
        int fd = appctx->ctx.cli.i0;
+       int ret = 1;
 
        if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
-               return 1;
+               goto end;
 
        chunk_reset(&trash);
 
+       /* isolate the threads once per round. We're limited to a buffer worth
+        * of output anyway, it cannot last very long.
+        */
+       thread_isolate();
+
        /* we have two inner loops here, one for the proxy, the other one for
         * the buffer.
         */
@@ -883,14 +889,10 @@ static int cli_io_handler_show_fd(struct appctx *appctx)
                void *ctx = NULL;
                uint32_t conn_flags = 0;
 
-               thread_isolate();
-
                fdt = fdtab[fd];
 
-               if (!fdt.owner) {
-                       thread_release();
+               if (!fdt.owner)
                        goto skip; // closed
-               }
 
                if (fdt.iocb == conn_fd_handler) {
                        conn_flags = ((struct connection *)fdt.owner)->flags;
@@ -956,24 +958,26 @@ static int cli_io_handler_show_fd(struct appctx *appctx)
                                      li->bind_conf->frontend->id);
                }
 
-               thread_release();
-
                chunk_appendf(&trash, "\n");
 
                if (ci_putchk(si_ic(si), &trash) == -1) {
                        si_rx_room_blk(si);
-                       return 0;
+                       appctx->ctx.cli.i0 = fd;
+                       ret = 0;
+                       break;
                }
        skip:
                if (appctx->st2 == STAT_ST_END)
                        break;
 
                fd++;
-               appctx->ctx.cli.i0 = fd;
        }
 
+ end:
        /* dump complete */
-       return 1;
+
+       thread_release();
+       return ret;
 }
 
 /* This function dumps some activity counters used by developers and support to