Signals, Part 3: Advanced Signal Processing

By Danny Kalev, ITworld |  How-to

In our final discussion about signal processing, we'll cover advanced
issues, including signal suspension and waiting for a signal.

Obtaining the Current Signal Mask
The set of signals that the process is currently blocking is called
a "signal mask." Call sigprocmask() to obtain the current signal mask
or alter it:

int sigprocmask(int mode, const sigset_t * newmask, sigset_t
*oldmask);

The first argument takes one of the following values:

* SIG_BLOCK -- Add all signals in newmask to the current signal
mask.
* SIG_UNBLOCK -- Remove all signals in newmask from the current
signal mask.
* SIG_SETMASK -- Block only the signals in newmask; the rest are
unblocked.

If oldmask isn't NULL, the current signal mask (before sigprocmask()
was called) is copied to it. The following code retrieves the current
signal mask of a process:

sigset_t oldmask;
sigemptyset(&oldmask);
sigprocmask(SIG_BLOCK, NULL, &oldmask);

Blocking Signals
It's often necessary to block incoming signals in a piece of code that
manipulates data that the signal's handler may also modify. Consider
the following handler for a SIGALRM signal:

char *Flags=someString; /*a global string*/
void handleAlarm(int sig){
free(someString);
someString=NULL;
}

What happens if a SIGALRM signal is delivered while the program is
processing Flags?

for (i=0; i<10; ++i)
Flags[i]=CLEAR;

The results are disastrous. The handler frees Flags while the loop is
writing to it. To avoid such race conditions, we must block SIGALRM
before entering the loop and unblock it afterwards:

sigset_t alrm;
sigemptyset(&alrm);
sigaddset(&alrm, SIGALRM);
sigprocmask(SIG_BLOCK, &alrm, NULL); /*block*/
for (i=0; i<10; ++i) /*process Flags safely*/
Flags[i]=OK;
sigprocmask(SIG_UNBLOCK, &alrm, NULL);/*unblock*/

To list all currently pending signals, call the sigpending() function:

int sigpending(sigset_t * pending);

After calling sigpending(), pending will contain all currently blocked
signals.

Waiting for Signals
Event-based applications should wait for a signal to occur before
continuing. To do this, use the pause() function that is declared in
as follows:

int pause(void);

pause() doesn't return until after a signal has been delivered to the
process. If a matching handler for that signal exists, it executes
before pause() returns. Alternatively, you can call sigsuspend(), which
is declared in as follows:

int sigsuspend(const sigset_t * tempmask);

sigsuspend() suspends the process until a signal has been delivered.
But unlike pause(), it temporarily sets the process's mask to tempmask
before waiting for a signal to occur. Once the signal occurs, the
process's signal mask is restored to the value it had before sigsuspend
() was called.

Join us:
Facebook

Twitter

Pinterest

Tumblr

LinkedIn

Google+

Join us:
Facebook

Twitter

Pinterest

Tumblr

LinkedIn

Google+

Ask a Question