Handling #Signals could be done in two ways: by blocking and signal action. To ease the signal management, we could utilise functions like sigfillset()
, sigemptyset()
, sigaddset()
and sigdelset()
from signal.h
which their functions are described briefly below.
sigset_t set1;
sigfillset(&set1); // initialise the signal set; this includes all signals
// available on the operatin system
sigdelset(&set1, SIGINT); // remove SIGINT from the signal set
sigaddset(&set1, SIGINT); // add SIGINT to the signal set
sigemptyset(&set1); // remove all signals in the signal set
Blocking
Signal blocking can be useful in protecting the process from being interrupted while executing a critical task. The signal will be blocked until the Process# has completed its operations. This could be done using the function sigprocmask()
with parameters that specify which action to take (SIG_SETMASK
, SIG_BLOCK
, and SIG_UNBLOCK
), what signals are involved, and the returned current mask of blocked signals. A typical usage is shown as follows:
sigset_t set1;
sigfillset(&set1); // initialise the signal set
sigprocmask(SIG_SETMASK, &set1, NULL); // set the current mask of blocked
// signals as set1, which is all signals
sigprocmask(SIG_UNBLOCK, &set1, NULL); // unblock signals included in set1
Signal Action
Signal action allows more sophisticated method of Signal Handling. It is defined through struct sigaction
and activated via the function sigaction()
. sigaction()
requires 3 parameters to be passed in: the signal that we want to act on, the struct sigaction
that is used to handle the signal, and the returned parameter that specifies the current signal action (usually NULL
). The structure for struct sigaction
and its typical usecase is shown below:
struct sigaction {
void (*sa_handler) (int); // signal handler, typical values are SIG_DFL
// (default action), SIG_IGN (ignore signal) or an
// address of a function that take an integer
// argument
sigset_t sa_mask; // block signal mask during the signal handling
int sa_flags; // flag that will affect the signal behaviour
void (*sa_sigaction) // pointer to signal handler
};
struct sigaction sa;
sa.sa_handler = handler; // signal will be handled by handler()
sigemptyset(&sa.sa_mask); // don't block signal while handling signal
sigaction(SIGINT, &sa, NULL); // handler() will be called when encounter SIGINT
void handler(int signo) // the prototype of a typical signal handler
{
// ...
}
We could further expand its usage by another two signal jump functions from setjmp.h
that can affect the control flow# of the program: sigsetjmp()
and siglongjmp()
.