restoreSignals() + restoreAffinity() -> restoreProcessContext()

This commit is contained in:
Eelco Dolstra 2021-04-07 13:10:02 +02:00
parent 8a29052cb2
commit 9b9e703df4
9 changed files with 32 additions and 42 deletions

View file

@ -310,7 +310,7 @@ void printVersion(const string & programName)
void showManPage(const string & name) void showManPage(const string & name)
{ {
restoreSignals(); restoreProcessContext();
setenv("MANPATH", settings.nixManDir.c_str(), 1); setenv("MANPATH", settings.nixManDir.c_str(), 1);
execlp("man", "man", name.c_str(), nullptr); execlp("man", "man", name.c_str(), nullptr);
throw SysError("command 'man %1%' failed", name.c_str()); throw SysError("command 'man %1%' failed", name.c_str());
@ -373,7 +373,7 @@ RunPager::RunPager()
throw SysError("dupping stdin"); throw SysError("dupping stdin");
if (!getenv("LESS")) if (!getenv("LESS"))
setenv("LESS", "FRSXMK", 1); setenv("LESS", "FRSXMK", 1);
restoreSignals(); restoreProcessContext();
if (pager) if (pager)
execl("/bin/sh", "sh", "-c", pager, nullptr); execl("/bin/sh", "sh", "-c", pager, nullptr);
execlp("pager", "pager", nullptr); execlp("pager", "pager", nullptr);

View file

@ -50,7 +50,7 @@ std::unique_ptr<SSHMaster::Connection> SSHMaster::startCommand(const std::string
options.dieWithParent = false; options.dieWithParent = false;
conn->sshPid = startProcess([&]() { conn->sshPid = startProcess([&]() {
restoreSignals(); restoreProcessContext();
close(in.writeSide.get()); close(in.writeSide.get());
close(out.readSide.get()); close(out.readSide.get());
@ -110,7 +110,7 @@ Path SSHMaster::startMaster()
options.dieWithParent = false; options.dieWithParent = false;
state->sshMaster = startProcess([&]() { state->sshMaster = startProcess([&]() {
restoreSignals(); restoreProcessContext();
close(out.readSide.get()); close(out.readSide.get());

View file

@ -1116,7 +1116,7 @@ void runProgram2(const RunOptions & options)
Strings args_(options.args); Strings args_(options.args);
args_.push_front(options.program); args_.push_front(options.program);
restoreSignals(); restoreProcessContext();
if (options.searchPath) if (options.searchPath)
execvp(options.program.c_str(), stringsToCharPtrs(args_).data()); execvp(options.program.c_str(), stringsToCharPtrs(args_).data());
@ -1612,12 +1612,19 @@ void startSignalHandlerThread()
std::thread(signalHandlerThread, set).detach(); std::thread(signalHandlerThread, set).detach();
} }
void restoreSignals() static void restoreSignals()
{ {
if (sigprocmask(SIG_SETMASK, &savedSignalMask, nullptr)) if (sigprocmask(SIG_SETMASK, &savedSignalMask, nullptr))
throw SysError("restoring signals"); throw SysError("restoring signals");
} }
void restoreProcessContext()
{
restoreSignals();
restoreAffinity();
}
/* RAII helper to automatically deregister a callback. */ /* RAII helper to automatically deregister a callback. */
struct InterruptCallbackImpl : InterruptCallback struct InterruptCallbackImpl : InterruptCallback
{ {
@ -1680,10 +1687,11 @@ string showBytes(uint64_t bytes)
} }
// FIXME: move to libstore/build
void commonChildInit(Pipe & logPipe) void commonChildInit(Pipe & logPipe)
{ {
const static string pathNullDevice = "/dev/null"; const static string pathNullDevice = "/dev/null";
restoreSignals(); restoreProcessContext();
/* Put the child in a separate session (and thus a separate /* Put the child in a separate session (and thus a separate
process group) so that it has no controlling terminal (meaning process group) so that it has no controlling terminal (meaning

View file

@ -300,6 +300,11 @@ std::pair<int, std::string> runProgram(const RunOptions & options);
void runProgram2(const RunOptions & options); void runProgram2(const RunOptions & options);
/* Restore the original inherited Unix process context (such as signal
masks, stack size, CPU affinity). */
void restoreProcessContext();
class ExecError : public Error class ExecError : public Error
{ {
public: public:
@ -513,9 +518,6 @@ class Callback;
on the current thread (and thus any threads created by it). */ on the current thread (and thus any threads created by it). */
void startSignalHandlerThread(); void startSignalHandlerThread();
/* Restore default signal handling. */
void restoreSignals();
struct InterruptCallback struct InterruptCallback
{ {
virtual ~InterruptCallback() { }; virtual ~InterruptCallback() { };

View file

@ -422,8 +422,6 @@ static void main_nix_build(int argc, char * * argv)
} else } else
env[var.first] = var.second; env[var.first] = var.second;
restoreAffinity();
/* Run a shell using the derivation's environment. For /* Run a shell using the derivation's environment. For
convenience, source $stdenv/setup to setup additional convenience, source $stdenv/setup to setup additional
environment variables and shell functions. Also don't environment variables and shell functions. Also don't
@ -473,7 +471,7 @@ static void main_nix_build(int argc, char * * argv)
auto argPtrs = stringsToCharPtrs(args); auto argPtrs = stringsToCharPtrs(args);
restoreSignals(); restoreProcessContext();
logger->stop(); logger->stop();

View file

@ -462,8 +462,7 @@ struct CmdDevelop : Common, MixEnvironment
auto args = phase || !command.empty() ? Strings{std::string(baseNameOf(shell)), rcFilePath} auto args = phase || !command.empty() ? Strings{std::string(baseNameOf(shell)), rcFilePath}
: Strings{std::string(baseNameOf(shell)), "--rcfile", rcFilePath}; : Strings{std::string(baseNameOf(shell)), "--rcfile", rcFilePath};
restoreAffinity(); restoreProcessContext();
restoreSignals();
execvp(shell.c_str(), stringsToCharPtrs(args).data()); execvp(shell.c_str(), stringsToCharPtrs(args).data());

View file

@ -42,7 +42,8 @@ struct CmdEdit : InstallableCommand
auto args = editorFor(pos); auto args = editorFor(pos);
restoreSignals(); restoreProcessContext();
execvp(args.front().c_str(), stringsToCharPtrs(args).data()); execvp(args.front().c_str(), stringsToCharPtrs(args).data());
std::string command; std::string command;

View file

@ -343,24 +343,6 @@ StringSet NixRepl::completePrefix(string prefix)
} }
static int runProgram(const string & program, const Strings & args)
{
Strings args2(args);
args2.push_front(program);
Pid pid;
pid = fork();
if (pid == -1) throw SysError("forking");
if (pid == 0) {
restoreAffinity();
execvp(program.c_str(), stringsToCharPtrs(args2).data());
_exit(1);
}
return pid.wait();
}
bool isVarName(const string & s) bool isVarName(const string & s)
{ {
if (s.size() == 0) return false; if (s.size() == 0) return false;
@ -462,7 +444,7 @@ bool NixRepl::processLine(string line)
auto args = editorFor(pos); auto args = editorFor(pos);
auto editor = args.front(); auto editor = args.front();
args.pop_front(); args.pop_front();
runProgram(editor, args); runProgram(editor, true, args);
// Reload right after exiting the editor // Reload right after exiting the editor
state->resetFileCache(); state->resetFileCache();
@ -481,7 +463,7 @@ bool NixRepl::processLine(string line)
state->callFunction(f, v, result, Pos()); state->callFunction(f, v, result, Pos());
StorePath drvPath = getDerivationPath(result); StorePath drvPath = getDerivationPath(result);
runProgram(settings.nixBinDir + "/nix-shell", Strings{state->store->printStorePath(drvPath)}); runProgram(settings.nixBinDir + "/nix-shell", true, {state->store->printStorePath(drvPath)});
} }
else if (command == ":b" || command == ":i" || command == ":s") { else if (command == ":b" || command == ":i" || command == ":s") {
@ -494,16 +476,18 @@ bool NixRepl::processLine(string line)
/* We could do the build in this process using buildPaths(), /* We could do the build in this process using buildPaths(),
but doing it in a child makes it easier to recover from but doing it in a child makes it easier to recover from
problems / SIGINT. */ problems / SIGINT. */
if (runProgram(settings.nixBinDir + "/nix", Strings{"build", "--no-link", drvPathRaw}) == 0) { try {
runProgram(settings.nixBinDir + "/nix", true, {"build", "--no-link", drvPathRaw});
auto drv = state->store->readDerivation(drvPath); auto drv = state->store->readDerivation(drvPath);
std::cout << std::endl << "this derivation produced the following outputs:" << std::endl; std::cout << std::endl << "this derivation produced the following outputs:" << std::endl;
for (auto & i : drv.outputsAndOptPaths(*state->store)) for (auto & i : drv.outputsAndOptPaths(*state->store))
std::cout << fmt(" %s -> %s\n", i.first, state->store->printStorePath(*i.second.second)); std::cout << fmt(" %s -> %s\n", i.first, state->store->printStorePath(*i.second.second));
} catch (ExecError &) {
} }
} else if (command == ":i") { } else if (command == ":i") {
runProgram(settings.nixBinDir + "/nix-env", Strings{"-i", drvPathRaw}); runProgram(settings.nixBinDir + "/nix-env", true, {"-i", drvPathRaw});
} else { } else {
runProgram(settings.nixBinDir + "/nix-shell", Strings{drvPathRaw}); runProgram(settings.nixBinDir + "/nix-shell", true, {drvPathRaw});
} }
} }

View file

@ -31,9 +31,7 @@ struct RunCommon : virtual Command
{ {
stopProgressBar(); stopProgressBar();
restoreSignals(); restoreProcessContext();
restoreAffinity();
/* If this is a diverted store (i.e. its "logical" location /* If this is a diverted store (i.e. its "logical" location
(typically /nix/store) differs from its "physical" location (typically /nix/store) differs from its "physical" location