[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
341/376: Use vfork
From: |
Ludovic Courtès |
Subject: |
341/376: Use vfork |
Date: |
Wed, 28 Jan 2015 22:06:03 +0000 |
civodul pushed a commit to tag 1.8
in repository guix.
commit 0e8fc118b3d2d3bb6f9b0a918bf8ceb3927774cd
Author: Eelco Dolstra <address@hidden>
Date: Wed Dec 10 16:35:42 2014 +0100
Use vfork
---
src/libutil/util.cc | 31 +++++++++++++++++++++++--------
src/libutil/util.hh | 12 ++++++++++--
src/nix-daemon/nix-daemon.cc | 7 ++++++-
3 files changed, 39 insertions(+), 11 deletions(-)
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 305e470..bdd114c 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -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;
}
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 628b8a0..09eb4d6 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -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
diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc
index 3864ab9..9a8f469 100644
--- a/src/nix-daemon/nix-daemon.cc
+++ b/src/nix-daemon/nix-daemon.cc
@@ -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;
- 326/376: Link against perl.dll on Cygwin, (continued)
- 326/376: Link against perl.dll on Cygwin, Ludovic Courtès, 2015/01/28
- 324/376: Set custom compiler flags on Cygwin, Ludovic Courtès, 2015/01/28
- 325/376: Fix library handling on Cygwin, Ludovic Courtès, 2015/01/28
- 335/376: Don't use RPATH on Darwin, Ludovic Courtès, 2015/01/28
- 337/376: Revert "Use posix_spawn to run the pager", Ludovic Courtès, 2015/01/28
- 334/376: Update signing.txt, Ludovic Courtès, 2015/01/28
- 336/376: Cruft, Ludovic Courtès, 2015/01/28
- 339/376: Include cacert in the binary tarball, Ludovic Courtès, 2015/01/28
- 340/376: Rename function, Ludovic Courtès, 2015/01/28
- 342/376: Don't do vfork in conjunction with setuid, Ludovic Courtès, 2015/01/28
- 341/376: Use vfork,
Ludovic Courtès <=
- 345/376: allow custom docbook paths/URLs, use a working URL for docbook.rng, Ludovic Courtès, 2015/01/28
- 344/376: Urgh, Ludovic Courtès, 2015/01/28
- 343/376: Provide default pagers, Ludovic Courtès, 2015/01/28
- 346/376: Don't use ?=, Ludovic Courtès, 2015/01/28
- 347/376: Remove canary stuff, Ludovic Courtès, 2015/01/28
- 348/376: Remove dead code, Ludovic Courtès, 2015/01/28
- 350/376: Doh, Ludovic Courtès, 2015/01/28
- 338/376: Don't wait for PID -1, Ludovic Courtès, 2015/01/28
- 352/376: Get rid of unnecessary "interrupted by the user" message with -vvv, Ludovic Courtès, 2015/01/28
- 353/376: Don't abort if we get a signal while waiting for the pager, Ludovic Courtès, 2015/01/28