mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-27 00:06:16 +02:00
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.
This commit is contained in:
parent
781d3dceb3
commit
2196fd1146
2 changed files with 61 additions and 2 deletions
|
@ -1748,13 +1748,39 @@ void triggerInterrupt()
|
|||
}
|
||||
|
||||
static sigset_t savedSignalMask;
|
||||
static bool savedSignalMaskIsSet = false;
|
||||
|
||||
void setChildSignalMask(sigset_t * sigs)
|
||||
{
|
||||
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();
|
||||
|
||||
if (sigprocmask(SIG_BLOCK, nullptr, &savedSignalMask))
|
||||
throw SysError("querying signal mask");
|
||||
saveSignalMask();
|
||||
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -448,6 +448,8 @@ void setStackSize(size_t stackSize);
|
|||
/**
|
||||
* Restore the original inherited Unix process context (such as signal
|
||||
* masks, stack size).
|
||||
|
||||
* See startSignalHandlerThread(), saveSignalMask().
|
||||
*/
|
||||
void restoreProcessContext(bool restoreMounts = true);
|
||||
|
||||
|
@ -817,9 +819,26 @@ class Callback;
|
|||
/**
|
||||
* Start a thread that handles various signals. Also block those signals
|
||||
* on the current thread (and thus any threads created by it).
|
||||
* Saves the signal mask before changing the mask to block those signals.
|
||||
* See saveSignalMask().
|
||||
*/
|
||||
void startSignalHandlerThread();
|
||||
|
||||
/**
|
||||
* Saves the signal mask, which is the signal mask that nix will restore
|
||||
* before creating child processes.
|
||||
* See setChildSignalMask() to set an arbitrary signal mask instead of the
|
||||
* current mask.
|
||||
*/
|
||||
void saveSignalMask();
|
||||
|
||||
/**
|
||||
* Sets the signal mask. Like saveSignalMask() but for a signal set that doesn't
|
||||
* necessarily match the current thread's mask.
|
||||
* See saveSignalMask() to set the saved mask to the current mask.
|
||||
*/
|
||||
void setChildSignalMask(sigset_t *sigs);
|
||||
|
||||
struct InterruptCallback
|
||||
{
|
||||
virtual ~InterruptCallback() { };
|
||||
|
|
Loading…
Reference in a new issue