logo

utils-std

Collection of commonly available Unix tools git clone https://anongit.hacktivis.me/git/utils-std.git/
commit: 05ba3f9bc9017f2542c002cd2f3d95554a02a102
parent 142e21a38b1a52929cbf63650778bf3ed74bd3e3
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Sun,  9 Nov 2025 20:13:51 +0100

cmd/time: propagate all signals to child

Diffstat:

Mcmd/time.17++-----
Mcmd/time.c68++++++++++++++++++++++++++++++++++++++++----------------------------
2 files changed, 42 insertions(+), 33 deletions(-)

diff --git a/cmd/time.1 b/cmd/time.1 @@ -43,11 +43,8 @@ could not be found .El .Sh SIGNALS .Nm -propagates -.Dv SIGTERM -and -.Dv SIGINT -to it's child process, allowing constructs like +propagates all signals to it's child process, +allowing constructs like .Ql timeout 1s time yes to work as expected. .Sh SEE ALSO diff --git a/cmd/time.c b/cmd/time.c @@ -29,23 +29,6 @@ enum cmd_time_mode }; static void -kill_child(int sig) -{ - if(child > 0) - { - if(kill(child, sig) != 0) - { - // candicate for sig2str - fprintf(stderr, - "time: warning: Failed propagating signal number %d to child process (%d): %s\n", - sig, - child, - strerror(errno)); - } - } -} - -static void usage(void) { fprintf(stderr, "Usage: time [-p|-v] command [argument ...]\n"); @@ -103,6 +86,15 @@ main(int argc, char *argv[]) return 1; } + sigset_t sigset; + if(sigfillset(&sigset) != 0) return 1; + + if(sigprocmask(SIG_BLOCK, &sigset, NULL) != 0) + { + fprintf(stderr, "time: error: Failed setting process' signal mask: %s\n", strerror(errno)); + return 1; + } + if(posix_spawnp(&child, argv[0], NULL, NULL, argv, environ) != 0) { ret = 126 + (errno == ENOENT); @@ -110,20 +102,40 @@ main(int argc, char *argv[]) return ret; } - struct sigaction sa = { - .sa_handler = &kill_child, - .sa_flags = 0, - }; + int status = 0; - if(sigaction(SIGTERM, &sa, NULL) != 0) - fprintf(stderr, "time: warning: Failed adding handler for SIGTERM: %s\n", strerror(errno)); + // Loop so signals are repeateadly propagated until child terminates + while(true) + { + int sig = -1; + if(sigwait(&sigset, &sig) != 0) + { + fprintf(stderr, "time: error: Failed waiting for signals: %s\n", strerror(errno)); + return 1; + } - if(sigaction(SIGINT, &sa, NULL) != 0) - fprintf(stderr, "time: warning: Failed adding handler for SIGINT: %s\n", strerror(errno)); + int ret = waitpid(child, &status, WNOHANG); + if(ret == child) + { + child = -1; + break; + } + else if(ret == -1) + { + fprintf(stderr, "time: error: Failed waiting for child process: %s\n", strerror(errno)); + return 1; + } - int status = 0; - waitpid(child, &status, 0); - child = -1; // reaped + if(kill(child, sig) != 0) + { + // candicate for sig2str + fprintf(stderr, + "time: warning: Failed propagating signal number %d to child process (%d): %s\n", + sig, + child, + strerror(errno)); + } + } clock_t t1 = times(&tms); if(t1 == -1)