aboutsummaryrefslogtreecommitdiff
path: root/src/libutil
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2017-02-01 13:00:21 +0100
committerEelco Dolstra <edolstra@gmail.com>2017-02-01 13:00:21 +0100
commit7a65b2470eb53a320749d76746fbf65790183d9d (patch)
tree696a327d3a17a676d9ab9b723e8abcd7a7cef3ed /src/libutil
parent583ff4ec46fe1fa758f0fa4df1d8b37d9192736c (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.cc24
-rw-r--r--src/libutil/util.hh7
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() { };