aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/util.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2014-12-10 16:35:42 +0100
committerEelco Dolstra <eelco.dolstra@logicblox.com>2014-12-10 17:25:39 +0100
commit0e8fc118b3d2d3bb6f9b0a918bf8ceb3927774cd (patch)
tree5f022418fc293841c649dceacd26e88e8a464c57 /src/libutil/util.cc
parentb5ed5b6e666e9d1e23b7cbc815684bfef52c3d41 (diff)
Use vfork
Diffstat (limited to 'src/libutil/util.cc')
-rw-r--r--src/libutil/util.cc31
1 files changed, 23 insertions, 8 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 305e470eb..bdd114c5e 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;
}