local/signal.c
///////////////////////////////////////////////////////////////////////////////
// Filename: signal.c
///////////////////////////////////////////////////////////////////////////////
// Purpose: demonstrates the use of signals
///////////////////////////////////////////////////////////////////////////////
// History:
// ========
//
// Date Time Name Description
// -------- -------- -------- ------------------------------------------------
// 96/03/19 01:11:12 muellerg: created
//
///////////////////////////////////////////////////////////////////////////////
// Feature test switches ///////////////////////////// Feature test switches //
/* NONE */
// System headers /////////////////////////////////////////// System headers //
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
// Local headers ///////////////////////////////////////////// Local headers //
#include "../common.h"
// Macros /////////////////////////////////////////////////////////// Macros //
/* NONE */
// File scope objects /////////////////////////////////// File scope objects //
/* NONE */
// External variables, functions, and classes ///////////// External objects //
/* NONE */
// Signal catching functions ///////////////////// Signal catching functions //
static void signalhandler(int signo)
{
cout << "Signal " << signo << " recognized!" << endl << flush;
return;
}
// Structures, unions, and class definitions /////////////////// Definitions //
/* NONE */
// Functions and class implementation /// Functions and class implementation //
/* NONE */
// Main /////////////////////////////////////////////////////////////// Main //
/* This example program shows how to protect the interrupt signal
* to be delivered in a critical region of code
*/
int
main(int argc, char *argv[])
{
error.set_program_name(argv[0]);
// signal masks
sigset_t newmask, oldmask, zeromask, testmask;
bool interrupted = false;
// set up signal handler
struct sigaction handle_sig;
handle_sig.sa_handler = &signalhandler; // function to call
sigemptyset(&handle_sig.sa_mask); // no need to block other signals
handle_sig.sa_flags = 0; // no special flags.
// set new handler into action
if(sigaction(SIGINT, &handle_sig, NULL) != 0)
error.system("sigaction error: can't install signal handler");
sigemptyset(&zeromask); // clear all signals in signal mask
sigemptyset(&newmask); // generate signal mask with SIGINT
sigaddset(&newmask, SIGINT);
// ...
// the program is doing some non-critical things
cout << "The program can be interrupted here with CTRL-C" << endl;
cout << "(sleeping for 5 seconds)" << endl;
sleep(5);
// ...
// now the program wants to make sure that it is not interrupted
// via the SIGINT signal: the SIGINT signal is blocked and the
// current signal mask saved
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
error.system("can't block signal");
cout << "Entering critical section... CTRL-C is not delivered..." << endl;
// now the program can do all the critical work...
sleep(5);
// ...
// We can test for a pending signal like this:
if(sigpending(&testmask) <0)
error.system("sigpending error");
if(sigismember(&testmask, SIGINT))
{
cout << "You have pressed CTRL-C in the critical section"
<< " without the signal beeing delivered to the process yet"
<< endl;
interrupted = true;
}
// The program might now want to wait for any signal
// sigsuspend() is used to atomically swap out the signal mask,
// while waiting for a signal.
cout << "Now all signals are delivered." << endl;
if(interrupted == false)
{
cout << "Please generate a signal for this process (e.g. by"
<< " pressing CTRL-C) to continue" << endl;
}
if(sigsuspend(&zeromask) != -1)
error.system("sigsuspend error");
// now reset signal mask which unblocks SIGINT
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
error.system("SIG_SETMASK error");
cout << "Now CTRL-C is recognized again. Sleeping for 5 seconds." << endl;
sleep(5);
// ...
return(EXIT_SUCCESS);
}