SignalHandler.cpp
/**
* Signal handling code, particularly SIGCHLD.
*/
#include "SignalHandler.h"
#include <cassert>
#include <cerrno>
#include <cstdio> // for perror
#include <cstdlib>
#include <iostream>
#include <signal.h>
#include <sys/wait.h>
using namespace std;
/** Print the specified exit status. */
static void printStatus(pid_t pid, int status)
{
if (WIFEXITED(status))
cerr << "PID " << pid << " exited with status "
<< WEXITSTATUS(status) << endl;
else if (WIFSIGNALED(status))
cerr << "PID " << pid << " killed by signal "
<< WTERMSIG(status) << endl;
else
cerr << "PID " << pid << " exited with code "
<< status << endl;
}
/** SIGCHLD handler. Reap child processes and report an error if any
* fail. */
static void sigchldHandler(int sig)
{
assert(sig == SIGCHLD);
(void)sig;
pid_t pid;
int status;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
// Writing to cerr in a signal handler is not allowed, but
// we're about to exit and an error message would be really
// helpful.
if (status != 0) {
printStatus(pid, status);
exit(EXIT_FAILURE);
}
}
if (pid == -1 && errno != ECHILD) {
perror("waitpid");
exit(EXIT_FAILURE);
}
}
/** Install a handler for SIGCHLD. */
void signalInit()
{
struct sigaction action;
action.sa_handler = sigchldHandler;
sigemptyset(&action.sa_mask);
action.sa_flags = SA_RESTART;
sigaction(SIGCHLD, &action, NULL);
}