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);
}