diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2017-02-01 13:00:21 +0100 |
---|---|---|
committer | Eelco Dolstra <edolstra@gmail.com> | 2017-02-01 13:00:21 +0100 |
commit | 7a65b2470eb53a320749d76746fbf65790183d9d (patch) | |
tree | 696a327d3a17a676d9ab9b723e8abcd7a7cef3ed /src/libutil | |
parent | 583ff4ec46fe1fa758f0fa4df1d8b37d9192736c (diff) |
Restore default signal handling in child processes
In particular, this fixes Ctrl-C in nix-shell sessions.
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/util.cc | 24 | ||||
-rw-r--r-- | src/libutil/util.hh | 7 |
2 files changed, 17 insertions, 14 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc index ca4edc2cd..6c4c5c969 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -860,6 +860,8 @@ string runProgram(Path program, bool searchPath, const Strings & args, Strings args_(args); args_.push_front(program); + restoreSignals(); + if (searchPath) execvp(program.c_str(), stringsToCharPtrs(args_).data()); else @@ -909,16 +911,6 @@ void closeOnExec(int fd) } -void restoreSIGPIPE() -{ - struct sigaction act; - act.sa_handler = SIG_DFL; - act.sa_flags = 0; - sigemptyset(&act.sa_mask); - if (sigaction(SIGPIPE, &act, 0)) throw SysError("resetting SIGPIPE"); -} - - ////////////////////////////////////////////////////////////////////// @@ -1218,19 +1210,31 @@ void triggerInterrupt() } } +static sigset_t savedSignalMask; + void startSignalHandlerThread() { + if (sigprocmask(SIG_BLOCK, nullptr, &savedSignalMask)) + throw SysError("quering signal mask"); + sigset_t set; sigemptyset(&set); sigaddset(&set, SIGINT); sigaddset(&set, SIGTERM); sigaddset(&set, SIGHUP); + sigaddset(&set, SIGPIPE); if (pthread_sigmask(SIG_BLOCK, &set, nullptr)) throw SysError("blocking signals"); std::thread(signalHandlerThread, set).detach(); } +void restoreSignals() +{ + if (sigprocmask(SIG_SETMASK, &savedSignalMask, nullptr)) + throw SysError("restoring signals"); +} + /* RAII helper to automatically deregister a callback. */ struct InterruptCallbackImpl : InterruptCallback { diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 07141ffed..cfaaf1486 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -256,10 +256,6 @@ void closeMostFDs(const set<int> & exceptions); /* Set the close-on-exec flag for the given file descriptor. */ void closeOnExec(int fd); -/* Restore default handling of SIGPIPE, otherwise some programs will - randomly say "Broken pipe". */ -void restoreSIGPIPE(); - /* User interruption. */ @@ -423,6 +419,9 @@ void callSuccess( on the current thread (and thus any threads created by it). */ void startSignalHandlerThread(); +/* Restore default signal handling. */ +void restoreSignals(); + struct InterruptCallback { virtual ~InterruptCallback() { }; |