mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Merge pull request #7931 from prattmic:zombie_signal
PiperOrigin-RevId: 471116527
This commit is contained in:
@@ -117,8 +117,17 @@ func (t *Task) killedLocked() bool {
|
||||
//
|
||||
// Preconditions: The caller must be running on the task goroutine.
|
||||
func (t *Task) PrepareExit(ws linux.WaitStatus) {
|
||||
t.tg.pidns.owner.mu.RLock()
|
||||
defer t.tg.pidns.owner.mu.RUnlock()
|
||||
t.tg.signalHandlers.mu.Lock()
|
||||
defer t.tg.signalHandlers.mu.Unlock()
|
||||
|
||||
last := t.tg.activeTasks == 1
|
||||
if last {
|
||||
t.prepareGroupExitLocked(ws)
|
||||
return
|
||||
}
|
||||
|
||||
t.exitStatus = ws
|
||||
}
|
||||
|
||||
@@ -133,6 +142,13 @@ func (t *Task) PrepareExit(ws linux.WaitStatus) {
|
||||
func (t *Task) PrepareGroupExit(ws linux.WaitStatus) {
|
||||
t.tg.signalHandlers.mu.Lock()
|
||||
defer t.tg.signalHandlers.mu.Unlock()
|
||||
t.prepareGroupExitLocked(ws)
|
||||
}
|
||||
|
||||
// Preconditions:
|
||||
// - The caller must be running on the task goroutine.
|
||||
// - The signal mutex must be locked.
|
||||
func (t *Task) prepareGroupExitLocked(ws linux.WaitStatus) {
|
||||
if t.tg.exiting || t.tg.execing != nil {
|
||||
// Note that if t.tg.exiting is false but t.tg.execing is not nil, i.e.
|
||||
// this "group exit" is being executed by the killed sibling of an
|
||||
|
||||
@@ -99,6 +99,68 @@ void RunChild() {
|
||||
abort();
|
||||
}
|
||||
|
||||
// SIGKILL of zombied thread group does not change exit status.
|
||||
TEST(ExitTest, SigkillZombieGroup) {
|
||||
int pipe_fds[2];
|
||||
ASSERT_THAT(pipe(pipe_fds), SyscallSucceeds());
|
||||
|
||||
FileDescriptor read_fd(pipe_fds[0]);
|
||||
FileDescriptor write_fd(pipe_fds[1]);
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
read_fd.reset();
|
||||
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
EXPECT_THAT(pid, SyscallSucceeds());
|
||||
write_fd.reset();
|
||||
|
||||
// Wait for pipe to automatically close to indicate that the child is zombied.
|
||||
char buf[10];
|
||||
EXPECT_THAT(ReadFd(read_fd.get(), buf, sizeof(buf)),
|
||||
SyscallSucceedsWithValue(0));
|
||||
|
||||
EXPECT_THAT(kill(pid, SIGKILL), SyscallSucceeds());
|
||||
|
||||
// SIGKILL did not change exit status.
|
||||
int status;
|
||||
EXPECT_THAT(RetryEINTR(waitpid)(pid, &status, 0), SyscallSucceeds());
|
||||
EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) << status;
|
||||
}
|
||||
|
||||
// Variant of SigkillZombieGroup using exit(2) instead of exit_group(2).
|
||||
TEST(ExitTest, SigkillZombieThread) {
|
||||
int pipe_fds[2];
|
||||
ASSERT_THAT(pipe(pipe_fds), SyscallSucceeds());
|
||||
|
||||
FileDescriptor read_fd(pipe_fds[0]);
|
||||
FileDescriptor write_fd(pipe_fds[1]);
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
read_fd.reset();
|
||||
|
||||
syscall(SYS_exit, 0);
|
||||
}
|
||||
|
||||
EXPECT_THAT(pid, SyscallSucceeds());
|
||||
write_fd.reset();
|
||||
|
||||
// Wait for pipe to automatically close to indicate that the child is zombied.
|
||||
char buf[10];
|
||||
EXPECT_THAT(ReadFd(read_fd.get(), buf, sizeof(buf)),
|
||||
SyscallSucceedsWithValue(0));
|
||||
|
||||
EXPECT_THAT(kill(pid, SIGKILL), SyscallSucceeds());
|
||||
|
||||
// SIGKILL did not change exit status.
|
||||
int status;
|
||||
EXPECT_THAT(RetryEINTR(waitpid)(pid, &status, 0), SyscallSucceeds());
|
||||
EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) << status;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace testing
|
||||
|
||||
Reference in New Issue
Block a user