Chapter Contents

Previous

Next
Signal-Handling Functions

Blocking Signals

Signals may be blocked to allow critical sections of code to run without interruption. The following functions control signal blocking:

sigprockmask and sigsuspend
block either SAS/C managed signals or USS signals. sigprocmask and sigsuspend are portable to POSIX-conforming systems.

sigblock , sigsetmask , and sigpause
are only used with SAS/C managed signals. These functions are portable to BSD UNIX operating systems.

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
specifies that the signals in the new signal mask should be blocked.

SIG_UNBLOCK
specifies that the signals in the new signal mask should not be blocked.

SIG_SETMASK
specifies that the new mask should replace the old mask.

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.  [cautionend]


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.  [cautionend]

Setting Up the Mask

The SAS/C library maintains a bit string called the signal mask that defines which asynchronous signals managed by SAS/C can be discovered and which of these signals are blocked. When a program begins execution no signals are blocked. If you set the mask to block a signal, the library does not discover an occurrence of the signal until that bit in the mask is reset. When you reset the mask to permit the signal to be discovered pending signals are then handled normally.

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 .

Note:    Signal blocking is meaningful only for asynchronous signals. Calls to these functions for synchronous signals do not generate errors; the calls have no effect.  [cautionend]

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);


Using sigsuspend and sigpause

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.