aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Bauer <mjbauer95@gmail.com>2022-09-03 00:27:16 -0500
committerMatthew Bauer <mjbauer95@gmail.com>2022-09-03 00:27:16 -0500
commit102434e4cbb8ed1b4075f99fb999f092fa068d5b (patch)
tree2132cf66739f3b554d360e0862926d237166694a
parent0c7f213c87c11c6c0f6b2fa07ba96548f6ea85ad (diff)
Disable SA_RESTART for some signals on macOS
Disables the SA_RESTART behavior on macOS which causes: > Restarting of pending calls is requested by setting the SA_RESTART bit > in sa_flags. The affected system calls include read(2), write(2), > sendto(2), recvfrom(2), sendmsg(2) and recvmsg(2) on a communications > channel or a slow device (such as a terminal, but not a regular file) > and during a wait(2) or ioctl(2). From: https://man.openbsd.org/sigaction#SA_RESTART This being set on macOS caused a bug where read() calls to the daemon socket were blocking after a SIGINT was received. As a result, checkInterrupt was never reached even though the signal was received by the signal handler thread. On Linux, SA_RESTART is disabled by default. This probably effects other BSDs but I don’t have the ability to test it there right now.
-rw-r--r--src/libmain/shared.cc13
1 files changed, 10 insertions, 3 deletions
diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc
index 31454e49d..0ee3fe772 100644
--- a/src/libmain/shared.cc
+++ b/src/libmain/shared.cc
@@ -194,9 +194,16 @@ void initNix()
/* HACK: on darwin, we need can’t use sigprocmask with SIGWINCH.
* Instead, add a dummy sigaction handler, and signalHandlerThread
* can handle the rest. */
- struct sigaction sa;
- sa.sa_handler = sigHandler;
- if (sigaction(SIGWINCH, &sa, 0)) throw SysError("handling SIGWINCH");
+ act.sa_handler = sigHandler;
+ if (sigaction(SIGWINCH, &act, 0)) throw SysError("handling SIGWINCH");
+
+ // Disable SA_RESTART for interrupts, so that system calls on this thread
+ // error with EINTR like they do on Linux, and we don’t hang forever.
+ act.sa_handler = SIG_DFL;
+ if (sigaction(SIGINT, &act, 0)) throw SysError("handling SIGINT");
+ if (sigaction(SIGTERM, &act, 0)) throw SysError("handling SIGTERM");
+ if (sigaction(SIGHUP, &act, 0)) throw SysError("handling SIGHUP");
+ if (sigaction(SIGPIPE, &act, 0)) throw SysError("handling SIGPIPE");
#endif
/* Register a SIGSEGV handler to detect stack overflows. */