Skip to content

Commit 5a7f9a5

Browse files
authored
[flang] use setsid to assign the child to prevent zombie as it will be clean up by init process (#77944)
When using `setsid()` in a child process created by `fork()`, a new session is created, and the child becomes a session leader. If the parent process terminates before the child, the child becomes an orphan and is adopted by the `init` process. The `init` process will eventually clean up the child process once it exits. However, killing the parent does not automatically kill the child; the child will continue running until it exits. Proper cleanup involves waiting for the child process to exit using `wait()` or `waitpid()` in the parent process to avoid zombie processes, but this approach is not valid for `EXECUTE_COMMAND_LINE` with async mode. Fix: #77803
1 parent eaa8def commit 5a7f9a5

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

flang/runtime/execute.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,6 @@ void RTNAME(ExecuteCommandLine)(const Descriptor &command, bool wait,
181181
}
182182
FreeMemory(wcmd);
183183
#else
184-
// terminated children do not become zombies
185-
signal(SIGCHLD, SIG_IGN);
186184
pid_t pid{fork()};
187185
if (pid < 0) {
188186
if (!cmdstat) {
@@ -192,6 +190,19 @@ void RTNAME(ExecuteCommandLine)(const Descriptor &command, bool wait,
192190
CheckAndCopyCharsToDescriptor(cmdmsg, "Fork failed");
193191
}
194192
} else if (pid == 0) {
193+
// Create a new session, let init process take care of zombie child
194+
if (setsid() == -1) {
195+
if (!cmdstat) {
196+
terminator.Crash("setsid() failed with errno: %d, asynchronous "
197+
"process initiation failed.",
198+
errno);
199+
} else {
200+
StoreIntToDescriptor(cmdstat, ASYNC_NO_SUPPORT_ERR, terminator);
201+
CheckAndCopyCharsToDescriptor(cmdmsg,
202+
"setsid() failed, asynchronous process initiation failed.");
203+
}
204+
exit(EXIT_FAILURE);
205+
}
195206
int status{std::system(newCmd)};
196207
TerminationCheck(status, cmdstat, cmdmsg, terminator);
197208
exit(status);

flang/unittests/Runtime/CommandTest.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,24 @@ TEST_F(ZeroArguments, ECLInvalidCommandParentNotTerminatedAsync) {
404404
CheckDescriptorEqStr(cmdMsg.get(), "No change");
405405
}
406406

407+
TEST_F(ZeroArguments, ECLInvalidCommandAsyncDontAffectSync) {
408+
OwningPtr<Descriptor> command{CharDescriptor("echo hi")};
409+
410+
EXPECT_NO_FATAL_FAILURE(RTNAME(ExecuteCommandLine)(
411+
*command.get(), false, nullptr, nullptr, nullptr));
412+
EXPECT_NO_FATAL_FAILURE(RTNAME(ExecuteCommandLine)(
413+
*command.get(), true, nullptr, nullptr, nullptr));
414+
}
415+
416+
TEST_F(ZeroArguments, ECLInvalidCommandAsyncDontAffectAsync) {
417+
OwningPtr<Descriptor> command{CharDescriptor("echo hi")};
418+
419+
EXPECT_NO_FATAL_FAILURE(RTNAME(ExecuteCommandLine)(
420+
*command.get(), false, nullptr, nullptr, nullptr));
421+
EXPECT_NO_FATAL_FAILURE(RTNAME(ExecuteCommandLine)(
422+
*command.get(), false, nullptr, nullptr, nullptr));
423+
}
424+
407425
static const char *oneArgArgv[]{"aProgram", "anArgumentOfLength20"};
408426
class OneArgument : public CommandFixture {
409427
protected:

0 commit comments

Comments
 (0)