aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/util.cc
diff options
context:
space:
mode:
authorRobert Hensing <robert@roberthensing.nl>2023-02-01 18:38:54 +0100
committerRobert Hensing <robert@roberthensing.nl>2023-04-07 17:50:40 +0200
commit2196fd1146aa077419a113059ced924a648f9766 (patch)
tree7ffaa7d10e176b9dd9225240f6a99a9f8777c807 /src/libutil/util.cc
parent781d3dceb303d9fceabe9a39eae0f7f986e1adcc (diff)
libutil: Provide alternatives to startSignalHandlerThread
How signals should be handled depends on what kind of process Nix is integrated into. The signal handler thread used by the stand-alone Nix commands / processes may not work well in the context of other runtime systems, such as those of Python, Perl, or Haskell.
Diffstat (limited to 'src/libutil/util.cc')
-rw-r--r--src/libutil/util.cc44
1 files changed, 42 insertions, 2 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 0099f7ebc..5c19dc737 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -1748,14 +1748,40 @@ void triggerInterrupt()
}
static sigset_t savedSignalMask;
+static bool savedSignalMaskIsSet = false;
-void startSignalHandlerThread()
+void setChildSignalMask(sigset_t * sigs)
{
- updateWindowSize();
+ assert(sigs); // C style function, but think of sigs as a reference
+
+#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
+ sigemptyset(&savedSignalMask);
+ // There's no "assign" or "copy" function, so we rely on (math) idempotence
+ // of the or operator: a or a = a.
+ sigorset(&savedSignalMask, sigs, sigs);
+#else
+ // Without sigorset, our best bet is to assume that sigset_t is a type that
+ // can be assigned directly, such as is the case for a sigset_t defined as
+ // an integer type.
+ savedSignalMask = *sigs;
+#endif
+
+ savedSignalMaskIsSet = true;
+}
+void saveSignalMask() {
if (sigprocmask(SIG_BLOCK, nullptr, &savedSignalMask))
throw SysError("querying signal mask");
+ savedSignalMaskIsSet = true;
+}
+
+void startSignalHandlerThread()
+{
+ updateWindowSize();
+
+ saveSignalMask();
+
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGINT);
@@ -1771,6 +1797,20 @@ void startSignalHandlerThread()
static void restoreSignals()
{
+ // If startSignalHandlerThread wasn't called, that means we're not running
+ // in a proper libmain process, but a process that presumably manages its
+ // own signal handlers. Such a process should call either
+ // - initNix(), to be a proper libmain process
+ // - startSignalHandlerThread(), to resemble libmain regarding signal
+ // handling only
+ // - saveSignalMask(), for processes that define their own signal handling
+ // thread
+ // TODO: Warn about this? Have a default signal mask? The latter depends on
+ // whether we should generally inherit signal masks from the caller.
+ // I don't know what the larger unix ecosystem expects from us here.
+ if (!savedSignalMaskIsSet)
+ return;
+
if (sigprocmask(SIG_SETMASK, &savedSignalMask, nullptr))
throw SysError("restoring signals");
}