about summary refs log tree commit diff
path: root/src/libutil/util.cc
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2017-02-01T12·00+0100
committerEelco Dolstra <edolstra@gmail.com>2017-02-01T12·00+0100
commit7a65b2470eb53a320749d76746fbf65790183d9d (patch)
tree696a327d3a17a676d9ab9b723e8abcd7a7cef3ed /src/libutil/util.cc
parent583ff4ec46fe1fa758f0fa4df1d8b37d9192736c (diff)
Restore default signal handling in child processes
In particular, this fixes Ctrl-C in nix-shell sessions.
Diffstat (limited to 'src/libutil/util.cc')
-rw-r--r--src/libutil/util.cc24
1 files changed, 14 insertions, 10 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index ca4edc2cd6..6c4c5c969d 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
 {