]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
DEBUG: cli: support closing "hard" using close() in addition to fd_delete()
authorWilly Tarreau <w@1wt.eu>
Tue, 5 Nov 2024 16:43:35 +0000 (17:43 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 5 Nov 2024 17:57:43 +0000 (18:57 +0100)
"debug dev close <fd>" currently closes that FD using fd_delete() after
checking that it's known from the fdtab. Sometimes we also want to just
perform a pure close() of FDs not in the fdtab (pollers, etc) in order
to provoke certain error cases. The optional "hard" argument to the
command will make it use a plain close() instead of fd_delete() and skip
the fd owner check. The main visible effect when closing a traffic socket
with it is that instead of dying from a double fd_delete() by seeing that
fd.owner is already 0, it will die during the next fd_insert() seeing that
fd.owner was not 0.

src/debug.c

index 20106ac1920e573804951bace6d78c1b7546ef5d..6c3bcbc730fbbc14d807452bbf66b429086fc9ae 100644 (file)
@@ -806,17 +806,23 @@ static int debug_parse_cli_close(char **args, char *payload, struct appctx *appc
                return 1;
 
        if (!*args[3])
-               return cli_err(appctx, "Missing file descriptor number.\n");
+               return cli_err(appctx, "Missing file descriptor number (optionally followed by 'hard').\n");
 
        fd = atoi(args[3]);
        if (fd < 0 || fd >= global.maxsock)
                return cli_err(appctx, "File descriptor out of range.\n");
 
+       if (strcmp(args[4], "hard") == 0) {
+               /* hard silent close, even for unknown FDs */
+               close(fd);
+               goto done;
+       }
        if (!fdtab[fd].owner)
                return cli_msg(appctx, LOG_INFO, "File descriptor was already closed.\n");
 
-       _HA_ATOMIC_INC(&debug_commands_issued);
        fd_delete(fd);
+ done:
+       _HA_ATOMIC_INC(&debug_commands_issued);
        return 1;
 }
 
@@ -2649,7 +2655,7 @@ REGISTER_PER_THREAD_INIT(feed_post_mortem_late);
 static struct cli_kw_list cli_kws = {{ },{
        {{ "debug", "dev", "bug", NULL },      "debug dev bug                           : call BUG_ON() and crash",                 debug_parse_cli_bug,   NULL, NULL, NULL, ACCESS_EXPERT },
        {{ "debug", "dev", "check", NULL },    "debug dev check                         : call CHECK_IF() and possibly crash",      debug_parse_cli_check, NULL, NULL, NULL, ACCESS_EXPERT },
-       {{ "debug", "dev", "close", NULL },    "debug dev close  <fd>                   : close this file descriptor",              debug_parse_cli_close, NULL, NULL, NULL, ACCESS_EXPERT },
+       {{ "debug", "dev", "close", NULL },    "debug dev close  <fd> [hard]            : close this file descriptor",              debug_parse_cli_close, NULL, NULL, NULL, ACCESS_EXPERT },
 #if !defined(USE_OBSOLETE_LINKER)
        {{ "debug", "dev", "counters", NULL }, "debug dev counters [all|bug|cnt|chk|?]* : dump/reset rare event counters",          debug_parse_cli_counters, debug_iohandler_counters, NULL, NULL, 0 },
 #endif