Restore default signal handling in child processes
In particular, this fixes Ctrl-C in nix-shell sessions.
This commit is contained in:
parent
583ff4ec46
commit
7a65b2470e
|
@ -30,6 +30,7 @@ static std::pair<FdSink, FdSource> connect(const string & conn)
|
|||
throw SysError("dupping stdin");
|
||||
if (dup2(from.writeSide, STDOUT_FILENO) == -1)
|
||||
throw SysError("dupping stdout");
|
||||
restoreSignals();
|
||||
execlp("ssh", "ssh", "-x", "-T", conn.c_str(), "nix-store --serve", NULL);
|
||||
throw SysError("executing ssh");
|
||||
});
|
||||
|
|
|
@ -119,15 +119,9 @@ void initNix()
|
|||
|
||||
startSignalHandlerThread();
|
||||
|
||||
/* Ignore SIGPIPE. */
|
||||
/* Reset SIGCHLD to its default. */
|
||||
struct sigaction act;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_handler = SIG_IGN;
|
||||
act.sa_flags = 0;
|
||||
if (sigaction(SIGPIPE, &act, 0))
|
||||
throw SysError("ignoring SIGPIPE");
|
||||
|
||||
/* Reset SIGCHLD to its default. */
|
||||
act.sa_handler = SIG_DFL;
|
||||
act.sa_flags = 0;
|
||||
if (sigaction(SIGCHLD, &act, 0))
|
||||
|
@ -252,7 +246,7 @@ void printVersion(const string & programName)
|
|||
|
||||
void showManPage(const string & name)
|
||||
{
|
||||
restoreSIGPIPE();
|
||||
restoreSignals();
|
||||
execlp("man", "man", name.c_str(), NULL);
|
||||
throw SysError(format("command ‘man %1%’ failed") % name.c_str());
|
||||
}
|
||||
|
@ -305,16 +299,6 @@ RunPager::RunPager()
|
|||
if (!pager) pager = getenv("PAGER");
|
||||
if (pager && ((string) pager == "" || (string) pager == "cat")) return;
|
||||
|
||||
/* Ignore SIGINT. The pager will handle it (and we'll get
|
||||
SIGPIPE). */
|
||||
struct sigaction act;
|
||||
act.sa_handler = SIG_IGN;
|
||||
act.sa_flags = 0;
|
||||
sigemptyset(&act.sa_mask);
|
||||
if (sigaction(SIGINT, &act, 0)) throw SysError("ignoring SIGINT");
|
||||
|
||||
restoreSIGPIPE();
|
||||
|
||||
Pipe toPager;
|
||||
toPager.create();
|
||||
|
||||
|
@ -323,6 +307,7 @@ RunPager::RunPager()
|
|||
throw SysError("dupping stdin");
|
||||
if (!getenv("LESS"))
|
||||
setenv("LESS", "FRSXMK", 1);
|
||||
restoreSignals();
|
||||
if (pager)
|
||||
execl("/bin/sh", "sh", "-c", pager, NULL);
|
||||
execlp("pager", "pager", NULL);
|
||||
|
@ -331,6 +316,8 @@ RunPager::RunPager()
|
|||
throw SysError(format("executing ‘%1%’") % pager);
|
||||
});
|
||||
|
||||
pid.setKillSignal(SIGINT);
|
||||
|
||||
if (dup2(toPager.writeSide.get(), STDOUT_FILENO) == -1)
|
||||
throw SysError("dupping stdout");
|
||||
}
|
||||
|
@ -345,7 +332,11 @@ RunPager::~RunPager()
|
|||
pid.wait();
|
||||
}
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
try {
|
||||
pid.kill(true);
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -400,6 +400,8 @@ void Goal::trace(const format & f)
|
|||
/* Common initialisation performed in child processes. */
|
||||
static void commonChildInit(Pipe & logPipe)
|
||||
{
|
||||
restoreSignals();
|
||||
|
||||
/* Put the child in a separate session (and thus a separate
|
||||
process group) so that it has no controlling terminal (meaning
|
||||
that e.g. ssh cannot open /dev/tty) and it doesn't receive
|
||||
|
@ -2662,8 +2664,6 @@ void DerivationGoal::runChild()
|
|||
for (auto & i : drv->args)
|
||||
args.push_back(rewriteStrings(i, inputRewrites));
|
||||
|
||||
restoreSIGPIPE();
|
||||
|
||||
/* Indicate that we managed to set up the build environment. */
|
||||
writeFull(STDERR_FILENO, string("\1\n"));
|
||||
|
||||
|
|
|
@ -91,6 +91,7 @@ ref<RemoteStore::Connection> SSHStore::openConnection()
|
|||
{
|
||||
if ((pid_t) sshMaster == -1) {
|
||||
sshMaster = startProcess([&]() {
|
||||
restoreSignals();
|
||||
if (key.empty())
|
||||
execlp("ssh", "ssh", "-N", "-M", "-S", socketPath.c_str(), uri.c_str(), NULL);
|
||||
else
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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() { };
|
||||
|
|
|
@ -452,6 +452,8 @@ int main(int argc, char ** argv)
|
|||
|
||||
auto argPtrs = stringsToCharPtrs(args);
|
||||
|
||||
restoreSignals();
|
||||
|
||||
execvp(getEnv("NIX_BUILD_SHELL", "bash").c_str(), argPtrs.data());
|
||||
|
||||
throw SysError("executing shell");
|
||||
|
|
Loading…
Reference in a new issue