Signals, Part 3: Advanced Signal Processing

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. Both pause() and sigsuspend() return -1 and set errno to EINTR.
What’s wrong? The new clean desk test
Join the discussion
Be the first to comment on this article. Our Commenting Policies