[flang-commits] [flang] 5a7f9a5 - [flang] use setsid to assign the child to prevent zombie as it will be clean up by init process (#77944)
via flang-commits
flang-commits at lists.llvm.org
Fri Jan 19 06:19:01 PST 2024
Author: Yi Wu
Date: 2024-01-19T14:18:57Z
New Revision: 5a7f9a5a9c85c9b7851bbf267f5a12b9211f810e
URL: https://github.com/llvm/llvm-project/commit/5a7f9a5a9c85c9b7851bbf267f5a12b9211f810e
DIFF: https://github.com/llvm/llvm-project/commit/5a7f9a5a9c85c9b7851bbf267f5a12b9211f810e.diff
LOG: [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: https://github.com/llvm/llvm-project/issues/77803
Added:
Modified:
flang/runtime/execute.cpp
flang/unittests/Runtime/CommandTest.cpp
Removed:
################################################################################
diff --git a/flang/runtime/execute.cpp b/flang/runtime/execute.cpp
index d38cb8384bc8640..c84930c5c3287c0 100644
--- a/flang/runtime/execute.cpp
+++ b/flang/runtime/execute.cpp
@@ -181,8 +181,6 @@ void RTNAME(ExecuteCommandLine)(const Descriptor &command, bool wait,
}
FreeMemory(wcmd);
#else
- // terminated children do not become zombies
- signal(SIGCHLD, SIG_IGN);
pid_t pid{fork()};
if (pid < 0) {
if (!cmdstat) {
@@ -192,6 +190,19 @@ void RTNAME(ExecuteCommandLine)(const Descriptor &command, bool wait,
CheckAndCopyCharsToDescriptor(cmdmsg, "Fork failed");
}
} else if (pid == 0) {
+ // Create a new session, let init process take care of zombie child
+ if (setsid() == -1) {
+ if (!cmdstat) {
+ terminator.Crash("setsid() failed with errno: %d, asynchronous "
+ "process initiation failed.",
+ errno);
+ } else {
+ StoreIntToDescriptor(cmdstat, ASYNC_NO_SUPPORT_ERR, terminator);
+ CheckAndCopyCharsToDescriptor(cmdmsg,
+ "setsid() failed, asynchronous process initiation failed.");
+ }
+ exit(EXIT_FAILURE);
+ }
int status{std::system(newCmd)};
TerminationCheck(status, cmdstat, cmdmsg, terminator);
exit(status);
diff --git a/flang/unittests/Runtime/CommandTest.cpp b/flang/unittests/Runtime/CommandTest.cpp
index 4c3618d0e3d903b..b2f6fe6177ed57e 100644
--- a/flang/unittests/Runtime/CommandTest.cpp
+++ b/flang/unittests/Runtime/CommandTest.cpp
@@ -404,6 +404,24 @@ TEST_F(ZeroArguments, ECLInvalidCommandParentNotTerminatedAsync) {
CheckDescriptorEqStr(cmdMsg.get(), "No change");
}
+TEST_F(ZeroArguments, ECLInvalidCommandAsyncDontAffectSync) {
+ OwningPtr<Descriptor> command{CharDescriptor("echo hi")};
+
+ EXPECT_NO_FATAL_FAILURE(RTNAME(ExecuteCommandLine)(
+ *command.get(), false, nullptr, nullptr, nullptr));
+ EXPECT_NO_FATAL_FAILURE(RTNAME(ExecuteCommandLine)(
+ *command.get(), true, nullptr, nullptr, nullptr));
+}
+
+TEST_F(ZeroArguments, ECLInvalidCommandAsyncDontAffectAsync) {
+ OwningPtr<Descriptor> command{CharDescriptor("echo hi")};
+
+ EXPECT_NO_FATAL_FAILURE(RTNAME(ExecuteCommandLine)(
+ *command.get(), false, nullptr, nullptr, nullptr));
+ EXPECT_NO_FATAL_FAILURE(RTNAME(ExecuteCommandLine)(
+ *command.get(), false, nullptr, nullptr, nullptr));
+}
+
static const char *oneArgArgv[]{"aProgram", "anArgumentOfLength20"};
class OneArgument : public CommandFixture {
protected:
More information about the flang-commits
mailing list