From acac56a2babe2fcc44cedb5c3542b59bb367970f Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Wed, 4 Oct 2023 15:17:42 -0500 Subject: [PATCH] Take exit code from SIGCHLD siginfo instead of wait. Trying to fix race condition where SIGCHLD happens before parent calls wait(). We need the signal handler doing longjmp() to reliably interrupt the poll() for timeout -i, but the kernel won't deliver exit status twice. --- toys/other/timeout.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/toys/other/timeout.c b/toys/other/timeout.c index ed4956a4..553a9469 100644 --- a/toys/other/timeout.c +++ b/toys/other/timeout.c @@ -34,11 +34,12 @@ GLOBALS( struct pollfd pfd; sigjmp_buf sj; - int fds[2], pid; + int fds[2], pid, rc; ) -static void handler(int sig) +static void handler(int sig, siginfo_t *si) { + TT.rc = si->si_status + ((si->si_code!=CLD_EXITED)<<7); siglongjmp(TT.sj, 1); } @@ -49,7 +50,6 @@ static long nantomil(struct timespec *ts) static void callback(char *argv[]) { - xsignal(SIGCHLD, SIG_DFL); if (!FLAG(foreground)) setpgid(0, 0); } @@ -68,7 +68,7 @@ void timeout_main(void) TT.pfd.events = POLLIN; TT.fds[1] = -1; if (sigsetjmp(TT.sj, 1)) goto done; - xsignal_flags(SIGCHLD, handler, SA_NOCLDSTOP); + xsignal_flags(SIGCHLD, handler, SA_NOCLDSTOP|SA_SIGINFO); TT.pid = xpopen_setup(toys.optargs+1, FLAG(i) ? TT.fds : 0, callback); xsignal(SIGTTIN, SIG_IGN); @@ -101,8 +101,7 @@ void timeout_main(void) if (TT.pfd.revents&POLLHUP) break; } done: - xsignal(SIGCHLD, SIG_DFL); - ii = xpclose_both(TT.pid, TT.fds); + xpclose_both(TT.pid, TT.fds); - if (FLAG(preserve_status) || !toys.exitval) toys.exitval = ii; + if (FLAG(preserve_status) || !toys.exitval) toys.exitval = TT.rc; } -- 2.39.2