forked from lix-project/lix
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
|
@ -1748,13 +1748,39 @@ void triggerInterrupt()
|
||||||
}
|
}
|
||||||
|
|
||||||
static sigset_t savedSignalMask;
|
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()
|
void startSignalHandlerThread()
|
||||||
{
|
{
|
||||||
updateWindowSize();
|
updateWindowSize();
|
||||||
|
|
||||||
if (sigprocmask(SIG_BLOCK, nullptr, &savedSignalMask))
|
saveSignalMask();
|
||||||
throw SysError("querying signal mask");
|
|
||||||
|
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
sigemptyset(&set);
|
sigemptyset(&set);
|
||||||
|
@ -1771,6 +1797,20 @@ void startSignalHandlerThread()
|
||||||
|
|
||||||
static void restoreSignals()
|
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))
|
if (sigprocmask(SIG_SETMASK, &savedSignalMask, nullptr))
|
||||||
throw SysError("restoring signals");
|
throw SysError("restoring signals");
|
||||||
}
|
}
|
||||||
|
|
|
@ -448,6 +448,8 @@ void setStackSize(size_t stackSize);
|
||||||
/**
|
/**
|
||||||
* Restore the original inherited Unix process context (such as signal
|
* Restore the original inherited Unix process context (such as signal
|
||||||
* masks, stack size).
|
* masks, stack size).
|
||||||
|
|
||||||
|
* See startSignalHandlerThread(), saveSignalMask().
|
||||||
*/
|
*/
|
||||||
void restoreProcessContext(bool restoreMounts = true);
|
void restoreProcessContext(bool restoreMounts = true);
|
||||||
|
|
||||||
|
@ -817,9 +819,26 @@ class Callback;
|
||||||
/**
|
/**
|
||||||
* Start a thread that handles various signals. Also block those signals
|
* Start a thread that handles various signals. Also block those signals
|
||||||
* on the current thread (and thus any threads created by it).
|
* 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();
|
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
|
struct InterruptCallback
|
||||||
{
|
{
|
||||||
virtual ~InterruptCallback() { };
|
virtual ~InterruptCallback() { };
|
||||||
|
|
Loading…
Reference in a new issue