Merge pull request #7931 from prattmic:zombie_signal

PiperOrigin-RevId: 471116527
This commit is contained in:
gVisor bot
2022-08-30 16:20:11 -07:00
2 changed files with 78 additions and 0 deletions
+16
View File
@@ -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
+62
View File
@@ -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