forked from lix-project/lix
Use vfork
This commit is contained in:
parent
b5ed5b6e66
commit
0e8fc118b3
3 changed files with 39 additions and 11 deletions
|
@ -863,31 +863,46 @@ void killUser(uid_t uid)
|
|||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
pid_t startProcess(std::function<void()> fun,
|
||||
bool dieWithParent, const string & errorPrefix, bool runExitHandlers)
|
||||
/* Wrapper around vfork to prevent the child process from clobbering
|
||||
the caller's stack frame in the parent. */
|
||||
static pid_t doFork(bool allowVfork, std::function<void()> fun) __attribute__((noinline));
|
||||
static pid_t doFork(bool allowVfork, std::function<void()> fun)
|
||||
{
|
||||
#ifdef __linux__
|
||||
pid_t pid = allowVfork ? vfork() : fork();
|
||||
#else
|
||||
pid_t pid = fork();
|
||||
if (pid == -1) throw SysError("unable to fork");
|
||||
#endif
|
||||
if (pid != 0) return pid;
|
||||
fun();
|
||||
abort();
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
|
||||
pid_t startProcess(std::function<void()> fun, const ProcessOptions & options)
|
||||
{
|
||||
auto wrapper = [&]() {
|
||||
_writeToStderr = 0;
|
||||
try {
|
||||
#if __linux__
|
||||
if (dieWithParent && prctl(PR_SET_PDEATHSIG, SIGKILL) == -1)
|
||||
if (options.dieWithParent && prctl(PR_SET_PDEATHSIG, SIGKILL) == -1)
|
||||
throw SysError("setting death signal");
|
||||
#endif
|
||||
restoreAffinity();
|
||||
fun();
|
||||
} catch (std::exception & e) {
|
||||
try {
|
||||
std::cerr << errorPrefix << e.what() << "\n";
|
||||
std::cerr << options.errorPrefix << e.what() << "\n";
|
||||
} catch (...) { }
|
||||
} catch (...) { }
|
||||
if (runExitHandlers)
|
||||
if (options.runExitHandlers)
|
||||
exit(1);
|
||||
else
|
||||
_exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
pid_t pid = doFork(options.allowVfork, wrapper);
|
||||
if (pid == -1) throw SysError("unable to fork");
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
|
|
@ -269,8 +269,16 @@ void killUser(uid_t uid);
|
|||
|
||||
/* Fork a process that runs the given function, and return the child
|
||||
pid to the caller. */
|
||||
pid_t startProcess(std::function<void()> fun, bool dieWithParent = true,
|
||||
const string & errorPrefix = "error: ", bool runExitHandlers = false);
|
||||
struct ProcessOptions
|
||||
{
|
||||
string errorPrefix;
|
||||
bool dieWithParent;
|
||||
bool runExitHandlers;
|
||||
bool allowVfork;
|
||||
ProcessOptions() : errorPrefix("error: "), dieWithParent(true), runExitHandlers(false), allowVfork(true) { };
|
||||
};
|
||||
|
||||
pid_t startProcess(std::function<void()> fun, const ProcessOptions & options = ProcessOptions());
|
||||
|
||||
|
||||
/* Run a program and return its stdout in a string (i.e., like the
|
||||
|
|
|
@ -799,6 +799,11 @@ static void daemonLoop(char * * argv)
|
|||
% (peer.uidKnown ? user : "<unknown>"));
|
||||
|
||||
/* Fork a child to handle the connection. */
|
||||
ProcessOptions options;
|
||||
options.errorPrefix = "unexpected Nix daemon error: ";
|
||||
options.dieWithParent = false;
|
||||
options.runExitHandlers = true;
|
||||
options.allowVfork = false;
|
||||
startProcess([&]() {
|
||||
fdSocket.close();
|
||||
|
||||
|
@ -821,7 +826,7 @@ static void daemonLoop(char * * argv)
|
|||
processConnection(trusted);
|
||||
|
||||
exit(0);
|
||||
}, false, "unexpected Nix daemon error: ", true);
|
||||
}, options);
|
||||
|
||||
} catch (Interrupted & e) {
|
||||
throw;
|
||||
|
|
Loading…
Reference in a new issue