]> git.kaiwu.me - haproxy.git/commitdiff
MINOR: sink: add timeout argument for "show events"
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 2 Nov 2026 16:03:36 +0000 (17:03 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 9 Nov 2026 16:21:16 +0000 (17:21 +0100)
Define a new "-u" argument for the CLI show events command. This allows
activating the uninterruptible execution mode for
cli_io_handler_show_ring(). The inactivity delay is directly derived
from the configured stats timeout.

doc/management.txt
src/ring.c
src/sink.c

index 7632544d08feca0a335e9b09675295ed99eff670..45d94176ccfa32b866f6d239d270879024aeae99 100644 (file)
@@ -3247,7 +3247,7 @@ show errors [<iid>|<proxy>] [request|response]
     error was at byte 23. This is the slash ('/') in header name
     "header/bizarre", which is not a valid HTTP character for a header name.
 
-show events  [-[wn0rs]*] [<sink>]
+show events  [-[wun0rs]*] [<sink>]
   With no option, this lists all known event sinks and their types. Arguments
   not starting with "-" are taken for a sink name, whose events will be dumped
   if it is of type buffer. The command also supports a variety of options
@@ -3284,7 +3284,16 @@ show events  [-[wn0rs]*] [<sink>]
         events and display them. It is possible to stop the operation by
         entering any input (which will be discarded) or by closing the session.
         Note that using "echo show events -w | socat ..." does close the input
-        and interrupt the dump.
+        and interrupt the dump; see '-u' option instead in this case.
+
+    -u  executes the command as an uninterruptible job. This is useful when
+        using utilities such as 'socat' to continue running after a half-close
+        of the CLI input. The command will still be stopped in this case if a
+        send error occurs while dumping new events or if no events are detected
+        after a delay based on the configured stats timeout.
+
+    Example :
+          $ echo "show events -u buf0" | socat -t10 - /var/run/haproxy.sock
 
 show fd [-!plcfbs]* [[<tgid>]/[<fd>] | <fd>]
   Dump the list of either all open file descriptors or just the one number <fd>
index e15dbb85be134597d7f9e10ab037ca0217bc9715..a7aba4494ff380d40340a99715318088ba1856d3 100644 (file)
@@ -838,6 +838,7 @@ void cli_io_release_show_ring(struct appctx *appctx)
        size_t ofs = ctx->ofs;
 
        ring_detach_appctx(ring, appctx, ofs);
+       cli_dec_unintr(appctx);
 }
 
 /* Returns the MAXIMUM payload len that could theoretically fit into the ring
index 7b1cfa1e837d663bbbecff13cb6d92df374461dc..46c5f810dcb218d15a1b31bae9ca2c25cea878a8 100644 (file)
@@ -358,7 +358,7 @@ static int cli_parse_show_events(char **args, char *payload, struct appctx *appc
        struct sink *sink;
        const char *name = NULL;
        uint ring_flags;
-       int arg;
+       int arg, ret, unintr = 0;
 
        ring_flags = 0;
        for (arg = 2; *args[arg]; arg++) {
@@ -377,6 +377,7 @@ static int cli_parse_show_events(char **args, char *payload, struct appctx *appc
                        case '0' : ring_flags |= RING_WF_END_ZERO;  break;
                        case 'n' : ring_flags |= RING_WF_SEEK_NEW;  break;
                        case 'w' : ring_flags |= RING_WF_WAIT_MODE; break;
+                       case 'u' : ring_flags |= RING_WF_WAIT_MODE; unintr = 1; break;
                        case 's' : ring_flags |= RING_WF_SANITIZE;  break;
                        case 'r' : ring_flags &= ~RING_WF_SANITIZE; break;
                        case 'h' : goto show_help;
@@ -388,7 +389,7 @@ static int cli_parse_show_events(char **args, char *payload, struct appctx *appc
        if (!name) {
                /* no arg => report the list of supported sink */
        show_help:
-               chunk_printf(&trash, "Supported events sinks are listed below. Add combinations of -0(zero), -w(wait), -n(new), -r(raw), -s(anitize). Any key to stop.\n");
+               chunk_printf(&trash, "Supported events sinks are listed below. Add combinations of -0(zero), -w(wait), -u(ninterruptible), -n(new), -r(raw), -s(anitize). Any key to stop.\n");
                list_for_each_entry(sink, &sink_list, sink_list) {
                        chunk_appendf(&trash, "    %-10s : type=%s, %u dropped, %s\n",
                                      sink->name,
@@ -412,7 +413,15 @@ static int cli_parse_show_events(char **args, char *payload, struct appctx *appc
        if (sink->type != SINK_TYPE_BUFFER)
                return cli_msg(appctx, LOG_NOTICE, "Nothing to report for this sink");
 
-       return ring_attach_cli(sink->ctx.ring, appctx, ring_flags);
+       if (unintr && cli_inc_unintr(appctx))
+               return cli_err(appctx, "Cannot start a new uninterruptible job");
+
+       ret = ring_attach_cli(sink->ctx.ring, appctx, ring_flags);
+       if (ret && unintr) {
+               /* attach failure, decrement uninterruptible job counter */
+               cli_dec_unintr(appctx);
+       }
+       return ret;
 }
 
 /* Pre-configures a ring proxy to emit connections */
@@ -1512,7 +1521,7 @@ REGISTER_POST_CHECK(sink_postcheck);
 REGISTER_POST_DEINIT(sink_deinit);
 
 static struct cli_kw_list cli_kws = {{ },{
-       { { "show", "events", NULL }, "show events [-0hnrsw]* [<sink>]         : show event sink state", cli_parse_show_events, NULL, NULL },
+       { { "show", "events", NULL }, "show events [-0hnrswu]* [<sink>]        : show event sink state", cli_parse_show_events, NULL, NULL },
        {{},}
 }};