Skip to content

Commit

Permalink
linux-sandbox-pid1: touch up the implementation of WaitForChild.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 333197486
  • Loading branch information
Googler authored and copybara-github committed Sep 23, 2020
1 parent 4fd17d3 commit 1517af1
Showing 1 changed file with 36 additions and 30 deletions.
66 changes: 36 additions & 30 deletions src/main/tools/linux-sandbox-pid1.cc
Original file line number Diff line number Diff line change
Expand Up @@ -428,36 +428,39 @@ static void SpawnChild() {
}
}

static void WaitForChild() {
while (1) {
// Check for zombies to be reaped and exit, if our own child exited.
static int WaitForChild() {
while (true) {
// Wait for some process to exit. This includes reparented processes in our
// PID namespace.
int status;
pid_t killed_pid = waitpid(-1, &status, 0);
PRINT_DEBUG("waitpid returned %d", killed_pid);

if (killed_pid < 0) {
// Our PID1 process got a signal that interrupted the waitpid() call and
// that was either ignored or forwared to the child. This is expected &
// fine, just continue waiting.
if (errno == EINTR) {
continue;
}
DIE("waitpid")
} else {
if (killed_pid == global_child_pid) {
// If the child process we spawned earlier terminated, we'll also
// terminate. We can simply _exit() here, because the Linux kernel will
// kindly SIGKILL all remaining processes in our PID namespace once we
// exit.
if (WIFSIGNALED(status)) {
PRINT_DEBUG("child died due to signal %d", WTERMSIG(status));
_exit(128 + WTERMSIG(status));
} else {
PRINT_DEBUG("child exited with code %d", WEXITSTATUS(status));
_exit(WEXITSTATUS(status));
}
}
const pid_t pid = TEMP_FAILURE_RETRY(wait(&status));

if (pid < 0) {
// We don't expect any errors besides EINTR. In particular, ECHILD should
// be impossible because we haven't yet seen global_child_pid exit.
DIE("wait");
}

PRINT_DEBUG("wait returned pid=%d, status=0x%02x", pid, status);

// If this isn't our child's PID, there's nothing further to do; we've
// successfully reaped a zombie.
if (pid != global_child_pid) {
continue;
}

// If the child exited due to a signal, log that fact and exit with the same
// status.
if (WIFSIGNALED(status)) {
const int signal = WTERMSIG(status);
PRINT_DEBUG("child exited due to signal %d", WTERMSIG(status));
return 128 + signal;
}

// Otherwise it must have exited normally.
const int exit_code = WEXITSTATUS(status);
PRINT_DEBUG("child exited normally with code %d", exit_code);
return exit_code;
}
}

Expand All @@ -479,6 +482,9 @@ int Pid1Main(void *sync_pipe_param) {
EnterSandbox();
SetupSignalHandlers();
SpawnChild();
WaitForChild();
_exit(EXIT_FAILURE);

// Note that there's no need to kill any remaining descendant processes; they
// are in our PID namespace and the kernel will send them SIGKILL
// automatically once we exit.
return WaitForChild();
}

0 comments on commit 1517af1

Please sign in to comment.