Skip to content

Commit

Permalink
Share the signal handling code between linux-sandbox and process-wrap…
Browse files Browse the repository at this point in the history
…per.

PiperOrigin-RevId: 156347327
  • Loading branch information
philwo authored and dslomov committed May 19, 2017
1 parent eae071c commit f590047
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 48 deletions.
25 changes: 0 additions & 25 deletions src/main/tools/linux-sandbox-pid1.cc
Original file line number Diff line number Diff line change
Expand Up @@ -325,31 +325,6 @@ static void EnterSandbox() {
}
}

static void InstallSignalHandler(int signum, void (*handler)(int)) {
struct sigaction sa = {};
sa.sa_handler = handler;
if (handler == SIG_IGN || handler == SIG_DFL) {
// No point in blocking signals when using the default handler or ignoring
// the signal.
if (sigemptyset(&sa.sa_mask) < 0) {
DIE("sigemptyset");
}
} else {
// When using a custom handler, block all signals from firing while the
// handler is running.
if (sigfillset(&sa.sa_mask) < 0) {
DIE("sigfillset");
}
}
// sigaction may fail for certain reserved signals. Ignore failure in this
// case, but report it in debug mode, just in case.
if (sigaction(signum, &sa, nullptr) < 0) {
PRINT_DEBUG("sigaction(%d, &sa, nullptr) failed", signum);
}
}

static void IgnoreSignal(int signum) { InstallSignalHandler(signum, SIG_IGN); }

// Reset the signal mask and restore the default handler for all signals.
static void RestoreSignalHandlersAndMask() {
// Use an empty signal mask for the process (= unblock all signals).
Expand Down
2 changes: 1 addition & 1 deletion src/main/tools/linux-sandbox.cc
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ int main(int argc, char *argv[]) {
CloseFds();

if (opt.timeout_secs > 0) {
HandleSignal(SIGALRM, OnTimeout);
InstallSignalHandler(SIGALRM, OnTimeout);
SetTimeout(opt.timeout_secs);
}

Expand Down
39 changes: 25 additions & 14 deletions src/main/tools/process-tools.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,27 +92,38 @@ void KillEverything(pid_t pgrp, bool gracefully, double graceful_kill_delay) {
kill(-pgrp, SIGKILL);
}

void HandleSignal(int sig, void (*handler)(int)) {
void InstallSignalHandler(int signum, void (*handler)(int)) {
struct sigaction sa = {};
sa.sa_handler = handler;
if (sigemptyset(&sa.sa_mask) < 0) {
DIE("sigemptyset");
if (handler == SIG_IGN || handler == SIG_DFL) {
// No point in blocking signals when using the default handler or ignoring
// the signal.
if (sigemptyset(&sa.sa_mask) < 0) {
DIE("sigemptyset");
}
} else {
// When using a custom handler, block all signals from firing while the
// handler is running.
if (sigfillset(&sa.sa_mask) < 0) {
DIE("sigfillset");
}
}
if (sigaction(sig, &sa, nullptr) < 0) {
if (sigaction(signum, &sa, nullptr) < 0) {
DIE("sigaction");
}
}

void UnHandle(int sig) {
switch (sig) {
case SIGSTOP:
case SIGKILL:
// These signals can't be handled, so they'll always have a valid default
// handler. In fact, even trying to install SIG_DFL again will result in
// EINVAL, so we'll just not do anything for these.
return;
default:
HandleSignal(sig, SIG_DFL);
void IgnoreSignal(int signum) {
// These signals can't be handled, so we'll just not do anything for these.
if (signum != SIGSTOP && signum != SIGKILL) {
InstallSignalHandler(signum, SIG_IGN);
}
}

void InstallDefaultSignalHandler(int signum) {
// These signals can't be handled, so we'll just not do anything for these.
if (signum != SIGSTOP && signum != SIGKILL) {
InstallSignalHandler(signum, SIG_DFL);
}
}

Expand Down
9 changes: 6 additions & 3 deletions src/main/tools/process-tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,13 @@ void Redirect(const std::string &target_path, int fd);
void KillEverything(pid_t pgrp, bool gracefully, double graceful_kill_delay);

// Set up a signal handler for a signal.
void HandleSignal(int sig, void (*handler)(int));
void InstallSignalHandler(int signum, void (*handler)(int));

// Revert signal handler for a signal to the default.
void UnHandle(int sig);
// Set the signal handler for `signum` to SIG_IGN (ignore).
void IgnoreSignal(int signum);

// Set the signal handler for `signum` to SIG_DFL (default).
void InstallDefaultSignalHandler(int sig);

// Use an empty signal mask for the process and set all signal handlers to their
// default.
Expand Down
10 changes: 5 additions & 5 deletions src/main/tools/process-wrapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,9 @@ static void SpawnCommand(const std::vector<char *> &args, double timeout_secs) {

// Set up a signal handler which kills all subprocesses when the given
// signal is triggered.
HandleSignal(SIGALRM, OnSignal);
HandleSignal(SIGTERM, OnSignal);
HandleSignal(SIGINT, OnSignal);
InstallSignalHandler(SIGALRM, OnSignal);
InstallSignalHandler(SIGTERM, OnSignal);
InstallSignalHandler(SIGINT, OnSignal);
if (timeout_secs > 0) {
SetTimeout(timeout_secs);
}
Expand All @@ -147,13 +147,13 @@ static void SpawnCommand(const std::vector<char *> &args, double timeout_secs) {

if (global_signal > 0) {
// Don't trust the exit code if we got a timeout or signal.
UnHandle(global_signal);
InstallDefaultSignalHandler(global_signal);
raise(global_signal);
} else if (WIFEXITED(status)) {
exit(WEXITSTATUS(status));
} else {
int sig = WTERMSIG(status);
UnHandle(sig);
InstallDefaultSignalHandler(sig);
raise(sig);
}
}
Expand Down

0 comments on commit f590047

Please sign in to comment.