From 102434e4cbb8ed1b4075f99fb999f092fa068d5b Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Sat, 3 Sep 2022 00:27:16 -0500 Subject: [PATCH 1/3] Disable SA_RESTART for some signals on macOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src/libmain/shared.cc | 13 ++++++++++--- 1 file 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. */ From a47b5476e1efb5c571f5a032a0b63ac8a2dfae82 Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Sat, 3 Sep 2022 16:06:33 -0500 Subject: [PATCH 2/3] Add more signals --- src/libmain/shared.cc | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 0ee3fe772..9769c993e 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -181,8 +181,9 @@ void initNix() /* Reset SIGCHLD to its default. */ struct sigaction act; sigemptyset(&act.sa_mask); - act.sa_handler = SIG_DFL; act.sa_flags = 0; + + act.sa_handler = SIG_DFL; if (sigaction(SIGCHLD, &act, 0)) throw SysError("resetting SIGCHLD"); @@ -197,13 +198,23 @@ void initNix() 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. + /* Disable SA_RESTART for interrupts, so that system calls on this thread + * error with EINTR like they do on Linux. + * Most signals on BSD systems default to SA_RESTART on, but Nix + * expects EINTR from syscalls to properly exit. */ 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"); + if (sigaction(SIGQUIT, &act, 0)) throw SysError("handling SIGQUIT"); + if (sigaction(SIGILL, &act, 0)) throw SysError("handling SIGILL"); + if (sigaction(SIGTRAP, &act, 0)) throw SysError("handling SIGTRAP"); + if (sigaction(SIGABRT, &act, 0)) throw SysError("handling SIGABRT"); + if (sigaction(SIGFPE, &act, 0)) throw SysError("handling SIGFPE"); + if (sigaction(SIGBUS, &act, 0)) throw SysError("handling SIGBUS"); + if (sigaction(SIGXCPU, &act, 0)) throw SysError("handling SIGXCPU"); + if (sigaction(SIGXFSZ, &act, 0)) throw SysError("handling SIGXFSZ"); #endif /* Register a SIGSEGV handler to detect stack overflows. */ From 77d3d3d18d181f4abe63d48361a96f4aac30668d Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Tue, 6 Sep 2022 09:47:53 -0500 Subject: [PATCH 3/3] Remove some signals --- src/libmain/shared.cc | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 9769c993e..52b75f757 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -208,13 +208,7 @@ void initNix() if (sigaction(SIGHUP, &act, 0)) throw SysError("handling SIGHUP"); if (sigaction(SIGPIPE, &act, 0)) throw SysError("handling SIGPIPE"); if (sigaction(SIGQUIT, &act, 0)) throw SysError("handling SIGQUIT"); - if (sigaction(SIGILL, &act, 0)) throw SysError("handling SIGILL"); if (sigaction(SIGTRAP, &act, 0)) throw SysError("handling SIGTRAP"); - if (sigaction(SIGABRT, &act, 0)) throw SysError("handling SIGABRT"); - if (sigaction(SIGFPE, &act, 0)) throw SysError("handling SIGFPE"); - if (sigaction(SIGBUS, &act, 0)) throw SysError("handling SIGBUS"); - if (sigaction(SIGXCPU, &act, 0)) throw SysError("handling SIGXCPU"); - if (sigaction(SIGXFSZ, &act, 0)) throw SysError("handling SIGXFSZ"); #endif /* Register a SIGSEGV handler to detect stack overflows. */