From 6b78f8de9edab04b520e6c6ed39bf7b36021d146 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Wed, 24 Aug 2022 17:27:18 -0700 Subject: [PATCH] timeout.c: fix for macOS. I don't know why we get away with this on Linux, but macOS really means business with the "values of objects of automatic storage invocation duration that do not have the volatile type and have been changed between the setjmp() invocation and longjmp() call are indeterminate" thing, leading to bad fds and a bad pid. Using volatile causes lots of warnings about passing `volatile int*` instead of `int*`, so it's a smaller change to move the fields into TT (and avoid the "automatic storage" part) than it is to add the `volatile` modifier. Four timeout tests fail on macOS (both locally and on github's CI) without this patch, and all timeout tests pass on macOS with this patch. --- toys/other/timeout.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/toys/other/timeout.c b/toys/other/timeout.c index 5e3cb204..2eac53d3 100644 --- a/toys/other/timeout.c +++ b/toys/other/timeout.c @@ -34,6 +34,7 @@ GLOBALS( struct pollfd pfd; sigjmp_buf sj; + int fds[2], pid; ) static void handler(int sig) @@ -48,9 +49,12 @@ static long nantomil(struct timespec *ts) void timeout_main(void) { - int fds[] = {0, -1}, ii, ms, nextsig, pid; + int ii, ms, nextsig; struct timespec tts, kts; + TT.fds[0] = 0; + TT.fds[1] = -1; + // Use same ARGFAIL value for any remaining parsing errors toys.exitval = 125; xparsetimespec(*toys.optargs, &tts); @@ -66,9 +70,9 @@ void timeout_main(void) TT.pfd.events = POLLIN; if (sigsetjmp(TT.sj, 1)) goto done; xsignal_flags(SIGCHLD, handler, SA_NOCLDSTOP); - pid = xpopen_both(toys.optargs+1, FLAG(i) ? fds : 0); - if (!FLAG(i)) xpipe(fds); - TT.pfd.fd = fds[1]; + TT.pid = xpopen_both(toys.optargs+1, FLAG(i) ? TT.fds : 0); + if (!FLAG(i)) xpipe(TT.fds); + TT.pfd.fd = TT.fds[1]; ms = nantomil(&tts); for (;;) { if (1 != xpoll(&TT.pfd, 1, ms)) { @@ -76,7 +80,7 @@ void timeout_main(void) perror_msg("sending signal %s to command %s", num_to_sig(nextsig), toys.optargs[1]); toys.exitval = (nextsig==9) ? 137 : 124; - kill(pid, nextsig); + kill(TT.pid, nextsig); if (!TT.k || nextsig==SIGKILL) break; nextsig = SIGKILL; ms = nantomil(&kts); @@ -85,7 +89,7 @@ void timeout_main(void) } if (TT.pfd.revents&POLLIN) { errno = 0; - if (1>(ii = read(fds[1], toybuf, sizeof(toybuf)))) { + if (1>(ii = read(TT.fds[1], toybuf, sizeof(toybuf)))) { if (errno==EINTR) continue; break; } @@ -95,7 +99,7 @@ void timeout_main(void) } done: xsignal(SIGCHLD, SIG_DFL); - ii = xpclose_both(pid, fds); + ii = xpclose_both(TT.pid, TT.fds); if (FLAG(preserve_status) || !toys.exitval) toys.exitval = ii; } -- 2.39.2