local tree, its contents will be displayed on the standard output. The format
is the same as the one described in "show ssl ocsp-response".
-wait { -h | <delay> } [<condition> [<args>...]]
+wait { -h | [-u] <delay> } [<condition> [<args>...]]
In its simplest form without any condition, this simply waits for the
requested delay before continuing. This can be used to collect metrics around
a specific interval.
+ Passing "-h" as the first or second argument provides the command's usage.
+
With a condition and optional arguments, the command will wait for the
specified condition to be satisfied, to unrecoverably fail, or to remain
unsatisfied for the whole <delay> duration. The supported conditions are:
the delay.
The default unit for the delay is milliseconds, though other units are
- accepted if suffixed with the usual timer units (us, ms, s, m, h, d). When
- used with the 'socat' utility, do not forget to extend socat's close timeout
- to cover the wait time. Passing "-h" as the first or second argument provides
- the command's usage.
+ accepted if suffixed with the usual timer units (us, ms, s, m, h, d).
+
+ By default, the command handler is interrupted as soon as the CLI input has
+ been closed which is the safest behavior. However, this causes issues with
+ utilities such as 'socat' which close their output channel only, as haproxy
+ is unable to differentiate between a full and a partial closure. Extra
+ argument '-u' can be specified to run the command in uninterruptible
+ execution mode. This is especially useful when using 'socat', at the
+ condition of the 'socat' close timeout being extended to cover the wait time.
+
Example:
- $ socat -t20 /path/to/socket - <<< "show activity; wait 10s; show activity"
+ $ socat -t20 /path/to/socket - <<< "show activity; wait -u 10s; show activity"
$ socat -t5 /path/to/socket - <<< "
disable server px/srv1
shutdown sessions server px/srv1
- wait 2s srv-removable px/srv1
+ wait -u 2s srv-removable px/srv1
del server px/srv1"
static int cli_parse_wait(char **args, char *payload, struct appctx *appctx, void *private)
{
struct cli_wait_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
- uint wait_ms;
+ uint wait_ms, unintr = 0;
const char *err;
if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
return 1;
+ if (strcmp(args[1], "-u") == 0) {
+ unintr = 1;
+ ++args;
+ }
+
if (!*args[1])
return cli_err(appctx, "Expects a duration in milliseconds.\n");
}
else if (*args[2]) {
/* show the command's help either upon request (-h) or error */
- err = "Usage: wait {-h|<duration>} [condition [args...]]\n"
+ err = "Usage: wait {-h|[-u] <duration>} [condition [args...]]\n"
" - '-h' displays this help\n"
+ " - '-u' activates uninterruptible mode\n"
" - <duration> is the maximum wait time, optionally suffixed by the unit among\n"
" 'us', 'ms', 's', 'm', 'h', and 'd'. ; the default unit is milliseconds.\n"
" - <condition> indicates what to wait for, no longer than the specified\n"
ctx->start = now_ms;
ctx->deadline = tick_add(now_ms, wait_ms);
+ if (unintr && cli_inc_unintr(appctx))
+ return cli_err(appctx, "Cannot start a new uninterruptible job.\n");
+
/* proceed with the I/O handler */
return 0;
}
wait:
/* Stop waiting upon close/abort/error */
- if (unlikely(se_fl_test(appctx->sedesc, SE_FL_SHW)) && !b_data(&appctx->inbuf)) {
+ if (!(appctx->cli_ctx.cmd_flags & CLI_CMD_FL_UNINTR) &&
+ unlikely(se_fl_test(appctx->sedesc, SE_FL_SHW)) && !b_data(&appctx->inbuf)) {
ctx->error = CLI_WAIT_ERR_INTR;
return 1;
}
char *msg = NULL;
int i;
+ cli_dec_unintr(appctx);
+
switch (ctx->error) {
case CLI_WAIT_ERR_EXP: memprintf(&msg, "Wait delay expired. %s\n", ctx->msg); break;
case CLI_WAIT_ERR_INTR: memprintf(&msg, "Interrupted. %s\n", ctx->msg); break;
{ { "show", "version", NULL }, "show version : show version of the current process", cli_parse_show_version, NULL, NULL, NULL, ACCESS_MASTER },
{ { "operator", NULL }, "operator : lower the level of the current CLI session to operator", cli_parse_set_lvl, NULL, NULL, NULL, ACCESS_MASTER},
{ { "user", NULL }, "user : lower the level of the current CLI session to user", cli_parse_set_lvl, NULL, NULL, NULL, ACCESS_MASTER},
- { { "wait", NULL }, "wait {-h|<delay_ms>} cond [args...] : wait the specified delay or condition (-h to see list)", cli_parse_wait, cli_io_handler_wait, cli_release_wait, NULL },
+ { { "wait", NULL }, "wait {-h|[-u] <delay_ms>} cond [args...] : wait the specified delay or condition (-h to see list)", cli_parse_wait, cli_io_handler_wait, cli_release_wait, NULL },
{ { "_send_status", NULL }, NULL, _send_status, NULL, NULL, NULL, ACCESS_MASTER_ONLY },
{{},}
}};