Chapter Contents |
Previous |
Next |
Signal-Handling Functions |
sigprockmask
and
sigsuspend
sigprocmask
and
sigsuspend
are portable to POSIX-conforming systems.
sigblock
,
sigsetmask
, and
sigpause
In general,
sigblock
,
sigsetmask
, and
sigpause
are provided for compatibility with previous releases
of SAS/C
and code that will be ported to BSD UNIX operating systems. You are encouraged
to use
sigprockmask
and
sigsuspend
when possible because they are more flexible, and they can
handle signals managed by both SAS/C and USS.
Using sigprocmask |
The
sigprocmask
function manipulates
a signal mask that determines which signals are blocked. A blocked signal
is not ignored; it is simply blocked from having any effect until the signal
mask is reset.
SIGKILL
and
SIGSTOP
cannot be blocked by
sigprocmask
; otherwise, all signals managed by USS may be blocked. You can also
use
sigprocmask
to block any of the asynchronous
signals managed by SAS/C.
The
sigprocmask
function
receives
sigset_t
structures for both a
new and an old signal mask.
sigprocmask
also requires one of the following
int
arguments that specify how to use these signal masks.
SIG_BLOCK
SIG_UNBLOCK
SIG_SETMASK
Here is an example that illustrates the
sigprocmask
function:
#include <sys/types.h> #include <signal.h> #include <lcsignal.h> #include <stdlib.h> main() { sigset_t omvsManaged, sascManaged, pendingSignals, newMask, oldMask; sigfillset(&omvsManaged); /* Request OpenEdition management */ sigemptyset(&sascManaged); /* of all signals. */ sigemptyset(&pendingSignals); sigemptyset(&newMask); sigemptyset(&oldMask); /* Tell the system which signals should be managed by SAS/C */ /* and which by OpenEdition. */ oesigsetup(&omvsManaged, &sascManaged); /* Block the SIGHUP signal. */ sigaddset(&newMask, SIGHUP); sigprocmask(SIG_BLOCK, &newMask, &oldMask); /* Actions to take while SIGHUP is blocked go here. */ /* Check to see if SIGHUP is pending. */ sigpending(&pendingSignals); if (sigismember(&pendingSignals, SIGHUP){ /* Actions to take if SIGHUP is pending go here. */ } /* Restore the old mask. */ sigprocmask(SIG_SETMASK, &oldMask, NULL); . . . }
Notice that if you don't like the defaults value for signal management
you must use
oesigsetup
to specify which
signals are managed by USS before you can use
sigprocmask
to block a signal.
The
sigpending
function can
be used to determine whether any signals are pending. A pending signal is
a blocked signal that has occurred and for which the signal action is still
pending. The
sigset_t
structure passed
to
sigpending
is filled with the pending
signals for the calling process. You can also use the
sigismember
function to determine if a specific signal is pending,
as illustrated in the previous example.
If a call to
sigprocmask
causes the signal mask to be changed so that one or more blocked signals
become unblocked, then at least one of these signals is delivered to the calling
process before the return from
sigprocmask
.
When the first signal is delivered, the signal mask changes according to the
action specified for that signal; this might or might not reblock any remaining
pending signals. If there are remaining pending signals blocked by the action
for the first signal, then on return from the handler, the previous mask is
restored and the next signal is delivered, and so on.
Note:
The
sigsuspend
function also modifies the
signal mask. See Using sigsuspend and sigpause for more information.
Using sigblock, sigsetmask, and sigpause |
The
sigblock
,
sigsetmask
, and
sigpause
functions
can also be used to block signals managed by SAS/C. However, these functions
cannot be used to block signals managed by USS.
Note:
None of the facilities described in this section are completely portable.
They are similar to facilities provided by the Berkeley 4.2 BSD UNIX implementation.
The
sigprocmask
function described in the
previous section provides a more flexible method of blocking signals.
When you generate a signal with
raise
or
siggen
, the library permits
the signal to be recognized even when it is blocked. Using the
sleep
function also permits the
SIGALRM
signal to be recognized even if it is blocked. In addition, the library
may block signals temporarily to preserve the integrity of its data areas
as it performs certain actions. When it has completed processing, the library
restores the mask defined by your program.
The library allows any asynchronous signal managed by
SAS/C (those defined by the library or
SIGASY1
through SIGASY8
) to be blocked by use of the functions
sigblock
,
sigsetmask
, and
sigpause
.
All of the signal-blocking functions require an argument
that changes the bit string used to mask signals, but the effect of the argument
differs among the functions. The
sigblock
function blocks the signals indicated by the argument but does not change
the rest of the mask.
sigsetmask
and
sigpause
reset the mask so that only the signals
indicated by the argument are blocked.
The form of the argument is the same for
sigblock
,
sigsetmask
, and
sigpause
. Use the left shift operator as shown
here to specify a mask for a single signal:
1<<(signal - 1)
The following call to
sigblock
sets the mask to block interrupt signals in addition to any other
masks already in effect:
/* Block SIGINT; retain rest of mask. */ sigblock(1<<(SIGINT - 1));
A similar call to
sigsetmask
changes the mask so that only interrupt signals are blocked:
sigsetmask(1<<(SIGINT - 1)); /* Block only SIGINT */
To block several signals with the
sigsetmask
function, use the bitwise OR operator. For example, this
code blocks both the interrupt signal and the user-defined signal
SIGASY1
:
/* Block SIGINT and SIGASY1. */ sigsetmask(1<<(SIGINT - 1)|1<<(SIGASY1 - 1));
Using Signal Blocking |
sigprocmask
,
sigblock
, and
sigsetmask
are typically
used to protect the execution of small sections of code that must
run without interruption. To do this, use one of the signal-blocking functions
to block interruptions before beginning the critical code. Then, when the
critical actions are completed, restore the mask that was in effect before
all signals were blocked. For example, the following code calls
sigprocmask
to block the additional signals identified by
blockedSignals
and store the previous mask in
oldMask
. Note that the new mask is the union of the current
signal
mask and the additional signals that are identified by
blockedSignals
. The example then calls
sigprocmask
a second time to restore the previous mask after the critical
code is completed:
sigprocmask(SIG_BLOCK, &blockedSignals, &oldMask); /* Block signals. */ take_ckpt(); /* Checkpoint data. */ sigprocmask(SIG_SETMASK, &oldmask, NULL); /* Restore previous mask. */
In this example, you could instead use
sigsetmask
and
sigblock
if you were
blocking only signals managed by SAS/C. Both
sigblock
and
sigsetmask
return the
previous signal mask. For example, you could call
sigblock
as follows to block all signals and store the value of the
old mask in
oldMask
:
oldMask = sigblock(0xffffffff);
Besides
sigprocmask
,
sigblock
, and
sigsetmask
, the library provides the
sigsuspend
and
sigpause
functions. These functions
combine the actions of the
pause
and
sigprocmask
functions. Here is an example of
a call to
sigsuspend
:
sigsuspend(&newMask);
The
call to
sigsuspend
has approximately the
same effect as the following code:
sigprocmask(SIG_SETMASK, &newMask, &oldMask); pause(); sigprocmask(SIG_SETMASK, &oldMask, NULL);
sigpause
is similar to
sigsuspend
except that its signal mask is in the BSD format rather than the POSIX
sigset_t
format, and it only allows you to change
the blocking of signals managed by SAS/C.
There is one important difference between the call to
sigsuspend
and the sequence of the other function
calls shown when
sigsuspend
is used: the
second call to
sigprocmask
occurs before
any handler is called.
sigsuspend
and
sigpause
are useful for interrupt-driven programs,
which can perform necessary processing with all signals blocked and then pause
with some or all signals unblocked when the program is ready to receive another
signal. If a signal is pending, the handler for that signal is called; otherwise,
the program waits until a new signal is received. In either case, the old
mask, which blocked all signals, is restored before the handler is called.
This ensures that no signals are discovered during execution of the handler,
which guarantees that all signals are processed one at a time in the order
they are received. Thus, processing of one signal is never interrupted by
another. Programs that process only one signal at a time are more reliable
and easier to write than those that permit interruption during most or all
of their execution. Refer to the example in the description of
sigpause
in Setting Up the Mask for an illustration of how to use these functions to process
one signal at
a time.
Signal blocking is useful even though, in many cases,
the library suspends processing of other asynchronous signals while a signal
handler is executing. Remember that the library allows processing of other
asynchronous signals as soon as the signal handler calls
signal
to reinstate signal handling. Even if the handler issues the
call to
signal
as the last instruction
in the function, the handler may not complete execution before the next signal
is discovered and handled.
Also, when you use
sigaction
to define a signal handler, you can use the arguments to
sigaction
to further control the blocking of signals within the handler.
A signal is blocked during execution of a handler for a signal discovered
during a call to
sigsuspend
or
sigpause
if it is blocked by either the signal mask in effect when
sigsuspend
or
sigpause
were called, or by the mask specified by
sigaction
.
Chapter Contents |
Previous |
Next |
Top of Page |
Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.