Skip to content

Commit

Permalink
[flang] use setsid to assign the child to prevent zombie as it will b…
Browse files Browse the repository at this point in the history
…e 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
  • Loading branch information
yi-wu-arm committed Jan 19, 2024
1 parent eaa8def commit 5a7f9a5
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 2 deletions.
15 changes: 13 additions & 2 deletions flang/runtime/execute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
Expand Down
18 changes: 18 additions & 0 deletions flang/unittests/Runtime/CommandTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down

0 comments on commit 5a7f9a5

Please sign in to comment.