Skip to content

Commit 9a5b27d

Browse files
committed
Add support for executing a detached process
1 parent 529b570 commit 9a5b27d

File tree

4 files changed

+26
-11
lines changed

4 files changed

+26
-11
lines changed

llvm/include/llvm/Support/Program.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ namespace sys {
152152
unsigned MemoryLimit = 0,
153153
std::string *ErrMsg = nullptr,
154154
bool *ExecutionFailed = nullptr,
155-
BitVector *AffinityMask = nullptr);
155+
BitVector *AffinityMask = nullptr,
156+
bool DetachProcess = false);
156157

157158
/// Return true if the given arguments fit within system-specific
158159
/// argument length limits.

llvm/lib/Support/Program.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ static bool Execute(ProcessInfo &PI, StringRef Program,
2727
std::optional<ArrayRef<StringRef>> Env,
2828
ArrayRef<std::optional<StringRef>> Redirects,
2929
unsigned MemoryLimit, std::string *ErrMsg,
30-
BitVector *AffinityMask);
30+
BitVector *AffinityMask, bool DetachProcess);
3131

3232
int sys::ExecuteAndWait(StringRef Program, ArrayRef<StringRef> Args,
3333
std::optional<ArrayRef<StringRef>> Env,
@@ -39,7 +39,7 @@ int sys::ExecuteAndWait(StringRef Program, ArrayRef<StringRef> Args,
3939
assert(Redirects.empty() || Redirects.size() == 3);
4040
ProcessInfo PI;
4141
if (Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg,
42-
AffinityMask)) {
42+
AffinityMask, /*DetachProcess*/ false)) {
4343
if (ExecutionFailed)
4444
*ExecutionFailed = false;
4545
ProcessInfo Result = Wait(
@@ -58,13 +58,14 @@ ProcessInfo sys::ExecuteNoWait(StringRef Program, ArrayRef<StringRef> Args,
5858
std::optional<ArrayRef<StringRef>> Env,
5959
ArrayRef<std::optional<StringRef>> Redirects,
6060
unsigned MemoryLimit, std::string *ErrMsg,
61-
bool *ExecutionFailed, BitVector *AffinityMask) {
61+
bool *ExecutionFailed, BitVector *AffinityMask,
62+
bool DetachProcess) {
6263
assert(Redirects.empty() || Redirects.size() == 3);
6364
ProcessInfo PI;
6465
if (ExecutionFailed)
6566
*ExecutionFailed = false;
6667
if (!Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg,
67-
AffinityMask))
68+
AffinityMask, DetachProcess))
6869
if (ExecutionFailed)
6970
*ExecutionFailed = true;
7071

llvm/lib/Support/Unix/Program.inc

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,11 @@ toNullTerminatedCStringArray(ArrayRef<StringRef> Strings, StringSaver &Saver) {
173173
}
174174

175175
static bool Execute(ProcessInfo &PI, StringRef Program,
176-
ArrayRef<StringRef> Args, std::optional<ArrayRef<StringRef>> Env,
176+
ArrayRef<StringRef> Args,
177+
std::optional<ArrayRef<StringRef>> Env,
177178
ArrayRef<std::optional<StringRef>> Redirects,
178179
unsigned MemoryLimit, std::string *ErrMsg,
179-
BitVector *AffinityMask) {
180+
BitVector *AffinityMask, bool DetachProcess) {
180181
if (!llvm::sys::fs::exists(Program)) {
181182
if (ErrMsg)
182183
*ErrMsg = std::string("Executable \"") + Program.str() +
@@ -202,7 +203,8 @@ static bool Execute(ProcessInfo &PI, StringRef Program,
202203
// If this OS has posix_spawn and there is no memory limit being implied, use
203204
// posix_spawn. It is more efficient than fork/exec.
204205
#ifdef HAVE_POSIX_SPAWN
205-
if (MemoryLimit == 0) {
206+
// Cannot use posix_spawn if you would like to detach the process
207+
if (MemoryLimit == 0 && !DetachProcess) {
206208
posix_spawn_file_actions_t FileActionsStore;
207209
posix_spawn_file_actions_t *FileActions = nullptr;
208210

@@ -270,7 +272,7 @@ static bool Execute(ProcessInfo &PI, StringRef Program,
270272

271273
return true;
272274
}
273-
#endif
275+
#endif // HAVE_POSIX_SPAWN
274276

275277
// Create a child process.
276278
int child = fork();
@@ -307,6 +309,14 @@ static bool Execute(ProcessInfo &PI, StringRef Program,
307309
}
308310
}
309311

312+
if (DetachProcess) {
313+
// Detach from controlling terminal
314+
if (setsid() == -1) {
315+
MakeErrMsg(ErrMsg, "Couldn't detach process, setsid() failed");
316+
return false;
317+
}
318+
}
319+
310320
// Set memory limits
311321
if (MemoryLimit != 0) {
312322
SetMemoryLimits(MemoryLimit);

llvm/lib/Support/Windows/Program.inc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,11 @@ static HANDLE RedirectIO(std::optional<StringRef> Path, int fd,
172172
} // namespace llvm
173173

174174
static bool Execute(ProcessInfo &PI, StringRef Program,
175-
ArrayRef<StringRef> Args, std::optional<ArrayRef<StringRef>> Env,
175+
ArrayRef<StringRef> Args,
176+
std::optional<ArrayRef<StringRef>> Env,
176177
ArrayRef<std::optional<StringRef>> Redirects,
177178
unsigned MemoryLimit, std::string *ErrMsg,
178-
BitVector *AffinityMask) {
179+
BitVector *AffinityMask, bool DetachProcess) {
179180
if (!sys::fs::can_execute(Program)) {
180181
if (ErrMsg)
181182
*ErrMsg = "program not executable";
@@ -284,6 +285,8 @@ static bool Execute(ProcessInfo &PI, StringRef Program,
284285
unsigned CreateFlags = CREATE_UNICODE_ENVIRONMENT;
285286
if (AffinityMask)
286287
CreateFlags |= CREATE_SUSPENDED;
288+
if (DetachProcess)
289+
CreateFlags |= DETACHED_PROCESS;
287290

288291
std::vector<wchar_t> CommandUtf16(Command.size() + 1, 0);
289292
std::copy(Command.begin(), Command.end(), CommandUtf16.begin());

0 commit comments

Comments
 (0)