[PATCH] Processes that spawn other processes should wait for their children to exit before exiting due to a signal.
Chris Bieneman
beanz at apple.com
Thu Apr 30 15:51:21 PDT 2015
Updating based on feedback from majnemer, ddunbar, and silvas.
http://reviews.llvm.org/D9420
Files:
lib/Support/Unix/Program.inc
Index: lib/Support/Unix/Program.inc
===================================================================
--- lib/Support/Unix/Program.inc
+++ lib/Support/Unix/Program.inc
@@ -21,8 +21,10 @@
#include "llvm/Config/config.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Signals.h"
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
@@ -61,10 +63,15 @@
#endif
#endif
+#include <vector>
+
namespace llvm {
using namespace sys;
+static bool ProgramSignalHandlerAdded = false;
+static ManagedStatic<std::vector<ProcessInfo>> ChildPIDs;
+
ProcessInfo::ProcessInfo() : Pid(0), ReturnCode(0) {}
ErrorOr<std::string> sys::findProgramByName(StringRef Name,
@@ -177,6 +184,18 @@
}
+// If a process that spawns other processes (like the clang driver) gets killed
+// via a SIGINT, it should wait until its children exit before returning from
+// the signal handler. This prevents the child processes from getting
+// re-parented, which causes problems for build systems that are the parent of
+// clang processes.
+static void WaitForChildren(void *) {
+ if (ChildPIDs.isConstructed())
+ for (auto PI : *ChildPIDs)
+ Wait(PI, /*SecondsUntilTerminate=*/0, /*WaitUntilTerminate=*/true,
+ /*ErrMsg=*/nullptr);
+}
+
static bool Execute(ProcessInfo &PI, StringRef Program, const char **args,
const char **envp, const StringRef **redirects,
unsigned memoryLimit, std::string *ErrMsg) {
@@ -187,6 +206,11 @@
return false;
}
+ if (!ProgramSignalHandlerAdded) {
+ AddSignalHandler(WaitForChildren, nullptr);
+ ProgramSignalHandlerAdded = true;
+ }
+
// If this OS has posix_spawn and there is no memory limit being implied, use
// posix_spawn. It is more efficient than fork/exec.
#ifdef HAVE_POSIX_SPAWN
@@ -250,6 +274,7 @@
return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err);
PI.Pid = PID;
+ ChildPIDs->push_back(PI);
return true;
}
@@ -314,12 +339,16 @@
}
PI.Pid = child;
+ ChildPIDs->push_back(PI);
return true;
}
namespace llvm {
+// This is assumed to be safe to call from within a signal handler. That means
+// it can't allocate or de-allocate memory or use any C interfaces not listed in
+// the sigaction man page.
ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,
bool WaitUntilTerminates, std::string *ErrMsg) {
#ifdef HAVE_SYS_WAIT_H
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D9420.24778.patch
Type: text/x-patch
Size: 2589 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150430/27784649/attachment.bin>
More information about the llvm-commits
mailing list