Using the signal classes

Signals allow one processes to interrupt the execution of another process.

Signal handlers allow processes to intercept and react to the signals sent to them.

Rudiments provides 3 classes for working with signals: signalset, signalmanager and signalhandler.

A signal set is just a collection of signals. The signalset class allows a programmer to build up a collection of signals.

The signalmanager class provides methods for sending signals, ignoring signals, waiting for signals and examining blocked signals.

The signalhandler class provides methods for catching and handling signals.

This program illustrates the use of all three classes.

> // Copyright (c) 2001 David Muse
> // See the file COPYING for more information
> #include <rudiments/signalclasses.h>
> #include <rudiments/stdio.h>
> bool gotsigterm=false;
> void handleSigterm(int32_t sig) {
> stdoutput.printf("Got a SIGTERM!\n");
> gotsigterm=true;
> }
> #ifdef SIGALRM
> void handleAlarm(int32_t sig) {
> stdoutput.printf("alarm!\n");
> }
> #endif
> int main(int argc, const char **argv) {
> // ignore all signals except SIGTERM and SIGALRM
> signalset ignoreset;
> ignoreset.addAllSignals();
> ignoreset.removeSignal(SIGTERM);
> #ifdef SIGALRM
> ignoreset.removeSignal(SIGALRM);
> #endif
> signalmanager::ignoreSignals(&ignoreset);
> // run handleSigterm() when a SIGTERM is received
> signalhandler termhandler;
> termhandler.setHandler(handleSigterm);
> termhandler.handleSignal(SIGTERM);
> // run handleAlarm() when a SIGALRM is received
> #ifdef SIGALRM
> signalhandler alarmhandler;
> alarmhandler.setHandler(handleAlarm);
> alarmhandler.handleSignal(SIGALRM);
> #endif
> // Loop forever, waiting to receive a signal that we are not ignoring.
> signalmanager::alarm(2);
> while (!gotsigterm) {
> signalmanager::waitForSignals(&ignoreset);
> signalmanager::alarm(2);
> }
> }

It should print out "alarm!" every 2 seconds and, if killed, should print out "Got a SIGTERM!" before exiting. If killed with a signal other than SIGTERM (the default), then it will ignore the signal.

Windows systems don't have signals or the kill program. Signals are more-or-less simulated on Windows platforms though, and the following program provides an approximation of the kill program as found on unix-like systems, that should work on Windows.

> #include <rudiments/process.h>
> #include <rudiments/charstring.h>
> #include <rudiments/error.h>
> #include <rudiments/stdio.h>
> int main(int argc, const char **argv) {
> if (argc<3) {
> stdoutput.printf("usage: kill signal processid\n");
> process::exit(1);
> }
> int32_t sig=SIGTERM;
> if (!charstring::compare(argv[1],"SIGINT")) {
> sig=SIGINT;
> } else if (!charstring::compare(argv[1],"SIGABRT")) {
> sig=SIGABRT;
> } else if (!charstring::compare(argv[1],"SIGFPE")) {
> sig=SIGFPE;
> } else if (!charstring::compare(argv[1],"SIGILL")) {
> sig=SIGILL;
> } else if (!charstring::compare(argv[1],"SIGSEGV")) {
> sig=SIGSEGV;
> } else if (!charstring::compare(argv[1],"SIGKILL")) {
> sig=SIGKILL;
> }
> pid_t pid=charstring::toInteger(argv[2]);
> if (!process::sendSignal(pid,sig)) {
> stdoutput.printf("kill failed: %s\n",error::getErrorString());
> process::exit(1);
> }
> process::exit(0);
> }