logo

utils-std

Collection of commonly available Unix tools git clone https://anongit.hacktivis.me/git/utils-std.git/
commit: 08147ec21ddca45950d806e72ebfba30f44dc3c3
parent bc2f5cfd41483c1a280c4c8cc36a2d90268db0de
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Sat, 13 Dec 2025 15:56:05 +0100

cmd/timeout: Fix SIGCHLD handler not exiting with timeout return code

Race-condition found via testing on OpenBSD

Diffstat:

Mcmd/timeout.c16+++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/cmd/timeout.c b/cmd/timeout.c @@ -35,16 +35,21 @@ extern char **environ; pid_t child = 0; const char *argv0 = "timeout"; +static bool timeout = false; +static int cmd_exit_timeout = CMD_EXIT_TIMEOUT; static void handle_sigchld(int sig) { + // Doesn't uses exit() to avoid running the atexit handlers + // one of which being gcc --coverage handler which causes a hang (void)sig; int stat_loc = 0; + + if(timeout && cmd_exit_timeout != 0) _Exit(CMD_EXIT_TIMEOUT); + waitpid(child, &stat_loc, WNOHANG); - // Not exit() to avoid running the atexit handlers - // one of which being gcc --coverage handler which causes a hang _Exit(WEXITSTATUS(stat_loc)); } @@ -62,7 +67,6 @@ main(int argc, char *argv[]) int term_sig = SIGTERM; const char *term_signame = "SIGTERM"; bool kill_child = true; - int cmd_exit_timeout = CMD_EXIT_TIMEOUT; char *arg = NULL; @@ -184,8 +188,8 @@ main(int argc, char *argv[]) argc--; struct sigaction sa = { - .sa_handler = handle_sigchld, - .sa_flags = 0, + .sa_handler = handle_sigchld, + .sa_flags = 0, }; if(sigaction(SIGCHLD, &sa, NULL) != 0) { @@ -222,6 +226,8 @@ main(int argc, char *argv[]) } } + timeout = true; + if(!kill_child) { return cmd_exit_timeout;