Signal-Handling Functions

Introduction

The signal-handling feature of the SAS/C library is a collection of library functions that enables you to handle unexpected conditions and interrupts during execution of a C program. Using this facility, you can

Release 6.00 of the SAS/C library provides OpenEdition and POSIX support for signal handling. Consequently, many new signals and signal-handling functions have been added to the library. Wherever possible, the SAS/C library preserves the behavior of previously existing signal-handling programs and treats POSIX signals and non-POSIX signals similarly. Where the POSIX definition of a signal and the SAS/C definition differ, a choice of behavior is offered on a per-signal basis.

Terminology Used in Signal Handling

This section introduces some of the terminology used to discuss the signal-handling features of the SAS/C library.
interrupt
is a hardware or software event that causes current processing to be suspended while the condition causing the interruption is processed. An interrupt can be processed either by the operating system or an application program or both.
signal
is an interrupt processed by the library, usually after processing by the operating system.
synchronous signal
is a signal directly resulting from program execution. For example, floating-point division by 0 generates a synchronous signal.
asynchronous signal
is a signal resulting from an interrupt external to the program. The timing of an asynchronous interrupt, in terms of program execution, is not predictable. For example, if you press the ATTN key while running a program under TSO, an asynchronous signal is generated. Because any program can send an OpenEdition signal to any other program, any signal defined by OpenEdition can be asynchronous.
discovery of a signal
is the time at which the library suspends normal program execution to respond to a signal. Synchronous signals are always discovered immediately, but asynchronous signals can only be discovered at certain points in execution, as described in the next section, "Types of Signal Support." Discovery of an asynchronous signal does not have to take place immediately after the occurrence of the original interrupt.
pending
is the state of a signal between the time of its occurrence and the time it is discovered.
signal blocking
is a processing technique for postponing discovery of an asynchronous signal. The program may specify one or more asynchronous signals that are to be blocked, and the set of blocked signals may be changed at any time. When a blocked signal occurs, program execution is unaffected until the program unblocks the signal. After it is unblocked, the signal will be discovered.

Types of Signal Support

With Release 6.00, signals are supported either directly by the SAS/C library or in cooperation with OpenEdition. To provide backward compatibility, a few differences exist between the way the SAS/C library manages signals and the way OpenEdition, with its POSIX support, manages them.

SAS/C Library

The SAS/C library distinguishes between synchronous and asynchronous signals. You can define signal handlers for both types of signals, but the timing for executing a handler differs depending on the type of signal. When a synchronous signal occurs, the handler for that signal is called immediately. When an asynchronous signal occurs, the library delays calling the handler until a function is called or returns or until the special function sigchk is called to discover pending asynchronous signals. See Discovering Asynchronous Signals for details on how the SAS/C library treats asynchronous signals.

Synchronous Signals

The synchronous signals defined by the library are

   SIGABND    SIGFPOFL   SIGMEM

   SIGABRT    SIGFPUFL   SIGSEGV

   SIGFPDIV   SIGIDIV    SIGTERM

   SIGFPE     SIGILL

 
Eight synchronous user signals (SIGUSR1 through SIGUSR8) are also available.

Asynchronous Signals

The asynchronous signals defined by the library are

   SIGALRM   SIGIUCV

   SIGINT

 
Eight asynchronous user signals (SIGASY1 through SIGASY8) are also available.

OpenEdition and POSIX

The POSIX.1 standard defines a large number of signals that may be sent to a process. Signals may be sent synchronously or asynchronously, but this does not depend on signal type. For instance, the signal SIGPIPE may be raised synchronously by OpenEdition when an attempt is made to read a pipe without a writer process, or it may be raised asynchronously by another process's use of the kill function to send this signal. Each signal has a default action, which is usually abnormal process termination, with some exceptions. For example, the default handling for the SIGTSTP signal is to suspend process execution.

Almost all signals can be blocked, which means they are delayed from having an effect on the target process until that process unblocks the signal. (Two signals, SIGKILL and SIGSTOP, cannot be blocked. These signals also cannot be handled and, therefore, always cause their default actions.)

Note: This definition differs considerably from the way SAS/C previously implemented signals. Traditionally, SAS/C only allowed asynchronous signals to be blocked. The synchronous/asynchronous distinction does not apply to POSIX signals, and blocking has an effect even on synchronously generated signals like SIGPIPE, with a few exceptions.

Supported Signals

The signals supported by Release 6.00 can be divided into three groups: signals managed only by SAS/C, signals managed exclusively by OpenEdition, and signals with dual support. For dual-support signals, you can define during program startup which signals are to be handled by OpenEdition and which are to be handled by the SAS/C library.

Signals managed exclusively by SAS/C are

SIGASY1-8
application-defined asynchronous signals
SIGFPDIV
floating-point division by 0
SIGFPOFL
floating-point overflow
SIGFPUFL
floating-point underflow
SIGIDIV
integer division by 0

SIGIUCV
VM inter-user communication signal
SIGMEM
no memory available for stack space
SIGUSR3-8
application-defined synchronous signals.
Signals managed exclusively by OpenEdition are
SIGCHLD
child process stopped
SIGCONT
continue process if stopped
SIGHUP
controlling terminal hangup
SIGKILL
process terminated (cannot be blocked)
SIGPIPE
write to a pipe that is not open for reading
SIGQUIT
interactively terminate process
SIGSTOP
process stopped (cannot be blocked)
SIGTRAP
debugging signal
SIGTSTP
interactively stop process
SIGTTIN
background process read from controlling terminal
SIGTTOU
background process write to controlling terminal.
Signals managed either by SAS/C or OpenEdition are
SIGABND
system ABEND
SIGABRT
abort function called
SIGALRM
real-time expiration signal
SIGFPE
general computational error
SIGILL
illegal instruction executed
SIGINT
interactive terminal attention signal
SIGIO
undefined
SIGSEGV
illegal memory access
SIGTERM
termination request
SIGUSR1-2
application-defined synchronous signals.
Each signal that may be managed by SAS/C is described in detail later in this section. See the POSIX.1 standard or The POSIX.1 Standard: A Programmer's Guide (Zlotnick 1991), for information on the signals defined by POSIX and managed by OpenEdition. All signals that can be used with the library have assigned numbers in the header file <signal.h>. Always refer to signals by their names, not their numbers, because signal numbers are not portable.

Note: The library permits you to raise the signals SIGIO and SIGTERM, but at the present it does not assign a meaning to these signals.

Choosing Signal Support Using oesigsetup

The oesigsetup function enables you to control which signals are managed by OpenEdition and which use support internal to the SAS/C library. oesigsetup must be called before any other signal-related function.

If there is no call to oesigsetup in a program called with exec linkage, the library assumes that all signals should be managed by OpenEdition, if possible. If there is no call to oesigsetup in a program not called with exec linkage (a regular batch or TSO execution), the library assumes that no signals should be managed by OpenEdition.

Note: This means that you must call oesigsetup in a program without exec linkage if you need to use OpenEdition signals.

The arguments to oesigsetup are two signal sets. The first defines the set of signals to be managed by OpenEdition, and the second defines the signals to be managed by SAS/C. oesigsetup fails if any signal is included in both sets; unspecified signals are handled as if oesigsetup had not been called.

Error Signals with Flexible Handling

The signals with flexible handling can be divided into two groups: error signals and other signals. The error signals, normally associated with program error condition, are SIGABND, SIGABRT, SIGFPE, SIGILL, and SIGSEGV. If these signals are handled as SAS/C conditions, OpenEdition is not informed of the error when the corresponding error condition occurs. If the error leads to termination, OpenEdition sets the final status of the terminated process to terminated by SIGKILL rather than a more specific status; otherwise, you can expect no undesirable effects.

Note: The SIGABND signal is used in Release 6.00 of SAS/C software to indicate a system ABEND. As described in the next section, this is a behavior change from previous versions of SAS/C.

Non-Error Signals with Flexible Handling

The non-error signals with flexible handling are SIGALRM, SIGINT, SIGIO, SIGTERM, SIGUSR1, and SIGUSR2. If OpenEdition handles SIGALRM, the SAS/C extension functions alarmd and sleepd are not available. If the SAS/C library handles SIGALRM, the ps shell command does not accurately indicate when the process is sleeping.

If SAS/C handles SIGINT, SIGINT is generated by use of the TSO attention key for a program running under TSO. If OpenEdition handles SIGINT, SAS/C does not use the STAX macro or attempt to handle TSO attentions. Be aware that SAS/C handling of SIGINT is not useful in non-TSO address spaces.

SIGIO has no special meaning at present to either OpenEdition or SAS/C but might be used by future versions of either product.

SIGTERM has no defined meaning to SAS/C and, therefore, can be generated only by use of the raise function if managed by SAS/C.

SIGUSR1 and SIGUSR2 have no special meaning to OpenEdition. If oesigsetup defines these signals as managed by SAS/C, then you can use SAS/C user-added signal support to define a meaning for one of these symbols.

Note: If you have defined a signal as handled by SAS/C and the signal is generated by OpenEdition, the result is always the OpenEdition default action for the signal. For example, if you define SIGTERM as a SAS/C signal and establish a handler, after which another process uses the kill function to send your process a SIGTERM signal, your handler will not be called and the process will be terminated.

A program can use kill to send a signal that oesigsetup has defined as a signal managed by SAS/C. If a program sends the signal to itself, only default handling will take place.

Handling Signals

Either the SAS/C library or OpenEdition defines a default action for each signal that can occur. If you want to override the default action for a signal, you can define a function called a signal handler that performs your own signal-handling actions. You can also request that the library or OpenEdition ignore some signals.

A signal handler may be identified by either the signal or the sigaction function, regardless of whether the signal is managed by SAS/C or OpenEdition. In general, sigaction is more flexible because it does not have to be reissued every time you enter a handler. However, signal is more portable because it is defined by the ISO/ANSI standard and it is defined by traditional UNIX C compilers; whereas, the

sigaction function is defined by the POSIX standard and is often not available with traditional UNIX C compilers.

Using signal

These basic actions are used to define a signal handler using the signal function defined by the ISO/ANSI standard:

The signal function requires two arguments: the name of the signal and the address of the function that handles the signal when it occurs. When a signal occurs, the handler defined by use of the signal function is called. The handler can do anything a normal C function can do. Frequently, a handler calls exit or abort to terminate program execution, or it calls longjmp to transfer control to a higher-level function. (For example, a handler for SIGINT may use longjmp to transfer control to the main function to immediately get new input from the terminal.)

After processing a signal, you may want the program to continue execution from the point at which it was interrupted. In this case, the handler simply executes a return statement. However, for some signals (such as SIGILL), it is impossible to resume at the point at which the signal occurred. If a signal handler returns in such a situation, the program is abnormally terminated.

The call to signal establishes signal handling for only one occurrence of a signal. Before the signal-handling function is called, the library resets the signal so that the default action is performed if the same signal occurs again. Resetting signal handling helps to prevent an infinite loop if, for example, an action performed in the signal handler raises the same signal again. If you want your handler to be used for a signal each time it occurs, you must call signal within the handler to reinstate it. You should be cautious in reinstating signal handling. For example, if you continually reinstate SIGINT handling, you may lose the ability to interrupt and terminate your program.

Using sigaction

These basic actions are used to define a signal handler using the sigaction function defined by the POSIX standard: As you can see from the previous list, the signal handling process used with sigaction is significantly different from the one used with signal. The sigaction structure, which contains information that describes the action to be performed when a signal is received, is defined as:
 struct sigaction {
    _HANDLER sa_handler;
    sigset_t sa_mask;
    int sa_flags;
 };
 
sa_handler is a pointer to the signal handler; sa_mask is the signal mask that will be used while the signal handler is running, and sa_flags specifies the flags that affect the handling of the signal.

Here is a brief example of how you can use the sigaction structure to define the action that should be performed when a SIGQUIT signal is received:

 extern void quitHandler(int);

 #include <unistd.h>
 #include <signal.h>

 main()
 {
    struct sigaction quitAction;

    quitAction.sa_handler = quitHandler;
    sigfillset(&quitAction.sa_mask);
    quitAction.sa_flags = 0;
    sigaction(SIGQUIT, &quitAction, NULL);
    .
    .
    .
 }

 void quitHandler(int signum)
 {
    .
    .  /* Signal handler code goes here. */
    .
 }
 
If this code is executed, the quitAction signal handler is called whenever a SIGQUIT signal is received. The call to sigfillset causes the quitAction.sa_mask to block all signals during the execution of the signal handler. Any signals blocked by the signal-action mask are delivered after the handler returns. Setting the quitAction.sa_flags to 0 specifies that no flags are used to modify the behavior of the signal. See the description of sigaction for a discussion of the signal action flags that you can specify.

Notice that the sigaction function does not require you to reinstate the signal handler within the signal handling function itself. The handling of a signal identified by sigaction is not reset to the default action after an occurrence of the signal. This behavior is different from the behavior of a signal handler identified by the signal function.

ABEND Handling

Before Release 6.00, SAS/C used the signal SIGTERM to represent a system ABEND of a C program. OpenEdition defines the signal SIGABND for this purpose. Therefore, with Release 6.00, SAS/C uses SIGABND rather than SIGTERM to represent an ABEND to be compatible with OpenEdition and to allow programs to handle SIGTERM in a more portable fashion.

Note: SIGABND has been assigned the old signal number for SIGTERM and SIGTERM has been given a new signal number. Thus, existing load modules that use the SIGTERM signal to intercept system ABENDs continue to work until they are recompiled.

SAS/C uses the signal SIGABRT to represent user ABENDs including library ABENDs. This is different from OpenEdition, which expects all ABENDs to be treated as SIGABND.

Note: If library ABEND handling is suppressed by the =nohtsig run-time option, or if library errors occur handling an ABEND, OpenEdition reports the status of an ABEND as terminated by SIGKILL rather than as terminated by SIGABND.

Getting More Information about a Signal

For some signals, you can get more information about the signal by calling the siginfo function in the signal handler. The siginfo function returns a pointer to the information associated with the signal being handled.

For example, when SIGMEM is raised, a call to siginfo provides information on the number of bytes of memory needed for additional stack space. If SIGFPE is raised, siginfo returns pointers to data that can be modified by the handler. For example, when SIGFPE is raised by a floating-point overflow, the information returned by siginfo includes the result of the computation that caused the overflow. You can replace this value and resume execution.

Some signals have no additional information available. If you call siginfo for one of these signals or if no signal has occurred, siginfo returns NULL. Refer to the descriptions of each signal for details on the information returned by siginfo. Table 5.1 summarizes the information returned by siginfo.

Note: siginfo is not a standard C function; avoid using it in programs that must be portable.

Table 5.1 Summary of Information from siginfo


   Signal    Information Returned by siginfo for Signals
              Raised Naturally
 

   SIGABND    pointer to structure of type ABND_t

   SIGABRT    pointer to structure of type ABRT_t

   SIGALRM    NULL

   SIGFPE     pointer to structure of type FPE_t

   SIGFPDIV   pointer to structure of type FPE_t

   SIGFPOFL   pointer to structure of type FPE_t

   SIGFPUFL   pointer to structure of type FPE_t

   SIGIDIV    pointer to structure of type FPE_t

   SIGILL     pointer to structure of type ILL_t

   SIGINT     NULL

   SIGIUCV    pointer to various types of structures; refer
              to Chapter 5, "Inter-User Communications
              Vehicle (IUCV) Functions," in the SAS/C
              Library Reference, Third Edition, Volume 2,&
              Release 6.00.

   SIGMEM     pointer to integer

   SIGSEGV    pointer to structure of type SEGV_t

   SIGTERM    NULL

 

The return value of siginfo is always 0 for any signal managed by OpenEdition, unless the signal was generated by siggen or the signal was a program check or ABEND directly associated with a program error.

Default Signal Handling

If you do not define a special handler for a signal or invoke a signal handler with the signal function and do not reinstate signal handling, the library performs default actions specific to each signal. You can also invoke default signal handling by using the special action SIG_DFL as the second argument to signal. For most signals, the default action is to abnormally terminate the program. Detailed discussions of default actions are in Signal Descriptions ; default actions are listed in Table 5.2.

Table 5.2 Summary of Default Actions


   Signal    Default Action         Default Action
              SAS/C Library          OpenEdition
              (SIG_DFL Handler)      (SIG_DFL Handler)
 

   SIGABND    ABEND with system code   ends the process
              ABE

   SIGABRT    ABEND with user code     ends the process
              1210

   SIGALRM    ABEND with user code     ends the process
              1225

   SIGCHLD    not supported            signal is ignored

   SIGCONT    not supported            continues a stopped
                                       process; otherwise,
                                       the signal is ignored

   SIGFPDIV   ABEND with 0CF.          not supported

   SIGFPE     raises another signal:   ends the process
              SIGFPOFL, SIGFPUFL,
              SIGFPDIV, or SIGIDIV.
              Refer to the
              descriptions of these
              signals for defaults.

   SIGFPOFL   ABEND with 0CC           not supported

   SIGFPUFL   changes result of        not supported
              computation to 0;
              execution continues

   SIGHUP     not supported            ends the process

   SIGKILL    not supported            ends the process

   SIGIDIV    ABEND with 0C9           not supported

   SIGILL     ABEND with appropriate   ends the process
              code (0C1, 0C2, 0C3,
              or 0C6)

   SIGINT     no default actions by    ends the process
              library; TSO default
              action is to ABEND;
              CMS default action
              ignores the signal

   SIGIO      ignored                  ignored

   SIGIUCV    ABEND with user code     not supported
              1225

   SIGMEM     attempts to continue     not supported
              execution; ABEND with
              code 80A (under TSO)
              or 0F7 (under CMS) if
              more than 4K of stack
              space is required.

   SIGPIPE    not supported            ends the process

   SIGQUIT    not supported            ends the process

   SIGSEGV    ABEND with appropriate   ends the process
              code (0C4 or 0C5)

   SIGSTOP    not supported            stops the process

   SIGTERM    ABEND with user code     ends the process
              1225

   SIGTRAP    not supported            ends the process

   SIGTSTP    not supported            stops the process

   SIGTTIN    not supported            stops the process

   SIGTTOU    not supported            stops the process
 

Ignoring Signals

If you want to ignore the occurrence of a signal, specify the special action SIG_IGN as the second argument to signal. Ignoring a signal causes the program to resume execution at the point at which the signal occurred. Some signals, such as SIGABRT, cannot be ignored because it is impossible to resume program execution at the point at which these signals occur.

Also, some signals such as SIGSEGV should not be ignored when they are managed by OpenEdition, even though it is possible to do so because the results are unpredictable. These signals are ignored if the specified action is SIG_IGN and they are generated by a call to the kill function; however, if the signal is generated by either a program check or an ABEND, the most likely result is that another ABEND will occur.

Table 5.3 lists which signals can be ignored. For more information, refer to the descriptions of the signals.

Table 5.3 Summary of Ignoring Signals


   Signal    SAS/C Library           OpenEdition
              Ignored Signals         Ignored Signals
              (SIG_IGN Handler)       (SIG_IGN Handler)
 

   SIGABND    cannot be ignored;       should not be
              ABEND as described in    ignored; results
              Table 5.2                unpredictable

   SIGABRT    cannot be ignored;       should not be
              ABEND as described in    ignored; results
              Table 5.2                unpredictable

   SIGALRM    program continues;       program continues;
              signal has no effect     signal has no effect

   SIGCHLD    not supported            program continues;
                                       signal has no effect

   SIGCONT    not supported            program continues;
                                       signal has no effect

   SIGFPDIV   program continues;       not supported
              result of computation
              undefined

   SIGFPE     program continues;       same as SAS/C
              result of computation
              undefined except for
              SIGFPUFL signals (see
              SIGFPUFL )

   SIGFPOFL   program continues;       not supported
              result of computation
              undefined

   SIGFPUFL   program continues;       not supported
              result of computation
              set to 0

   SIGHUP     not supported            program continues;
                                       signal has no effect

   SIGKILL    not supported            cannot be ignored

   SIGIDIV    program continues;       not supported
              result of computation
              undefined

   SIGILL     cannot be ignored;       should not be
              ABEND as described in    ignored; results
              Table 5.2                unpredictable

   SIGINT     use of ATTN or PA1 key   program continues;
              under MVS, or IC         signal has no effect
              command under CMS;
              signal has no effect

   SIGIO      program continues;       program continues;
              signal has no effect     signal has no effect

   SIGIUCV    cannot be ignored;       not supported
              ABEND as described in
              Table 5.2

   SIGMEM     execution continues      not supported
              until storage
              exhausted

   SIGPIPE    not supported            program continues;
                                       signal has no effect

   SIGQUIT    not supported            program continues;
                                       signal has no effect

   SIGSEGV    cannot be ignored;       should not be
              ABEND as described in    ignored; results
              Table 5.2                unpredictable

   SIGSTOP    not supported            cannot be ignored

   SIGTERM    program continues;       not supported
              signal has no effect

   SIGTRAP    not supported            program continues;
                                       signal has no effect

   SIGTSTP    not supported            program continues;
                                       signal has no effect

   SIGTTIN    not supported            program continues;
                                       signal has no effect

   SIGTTOU    not supported            program continues;
                                       signal has no effect
 

Generating Signals

In the normal execution of a program, signals occur at unpredictable times. As you write and test a program that handles signals, you may want to generate signals to ensure that your program handles them correctly. Your program also may need to generate signals as part of an error-checking routine. For example, a mathematical function may generate a SIGFPOFL signal if it determines that an overflow is certain to occur during its processing.

The library provides three functions for generating signals: raise, siggen, and kill.

If you raise a signal with raise or siggen the handler is called immediately, even if the signal is asynchronous, unless it is a blocked signal managed by OpenEdition. Therefore, these functions are not useful for testing signal blocking.

If you use raise or siggen to generate a signal with no special handler defined and the default action is abnormal termination, the program abnormally terminates. However, this abnormal termination may not be exactly the same as it would be if the signal had occurred naturally.

User-defined signals (SIGUSR1 through SIGUSR8 and SIGASY1 through SIGASY8) can be generated by using raise or siggen. Refer to Chapter 12, "User-Added Signals," in the SAS/C Library Reference, Volume 2 for another method of raising user-defined signals.

Discovering Asynchronous Signals

As mentioned earlier, the library calls handlers for synchronous signals as soon as the signal occurs; however, when an asynchronous signal occurs, the library may not immediately call the handler. There may be a delay because the signal must be discovered by the run-time library. After the signal is discovered, the library calls the handler. There are only three times asynchronous signals are discovered: You can insert calls to sigchk in your program to decrease the number of statements that are executed before a signal is discovered.

The library limits the times that an asynchronous signal can be discovered to improve your control of signal handling. There are two reasons the SAS/C library delays processing asynchronous signals:

This method of discovering asynchronous signals is a feature of the SAS/C implementation. If you are writing portable code be aware that, on some systems, handlers are always called immediately. In such systems, you must write code carefully to avoid incorrect results if signals are inconveniently timed.

Delaying Discovery of Signals

For many applications, coding a signal handler is complicated by the possibility that a new signal may be generated during the handler's execution (either the same signal or a completely unrelated signal). For POSIX applications, the sigaction function makes it easy to block signals during the execution of a signal handler. For non-POSIX applications, the situation is more complicated, and it may be difficult to block asynchronous signals during the execution of a signal handler. To assist in the writing of reliable code, the SAS/C library suppresses the discovery of new asynchronous signals within a handler. An exception is when the handler calls sigchk, signal, or sigaction, which indicates its readiness to handle new signals. This applies only to asynchronous signals; for example, if a handler divides by 0, the resulting signal cannot be delayed no matter how convenient that might be. Also, any signals that are pending while a handler executes are discovered and processed when the handler returns.

If you are writing portable code be aware that, on some systems, asynchronous signals are discovered even while a handler is executing. On such systems, you must write code carefully to avoid incorrect results if signals are inconveniently timed.

Waiting for Signals

Some programs are interrupt driven; that is, their operation is controlled by signals from external sources (for example, IUCV signals from other VM users). For such programs, it is important to have a waiting period without using CPU resources until a signal is received. The library provides the following functions for this purpose:

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 OpenEdition 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 OpenEdition.

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 OpenEdition 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 OpenEdition 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 OpenEdition.

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.

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.

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 on page 5-16 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.

Using Signals Portably

The SAS/C signal-handling implementation offers many extensions that make it easier to use than a completely standard implementation. However, if you use these extensions, your programs are not portable. Keep in mind these considerations when writing a program that you intend to be portable:

Using Signals Reliably

The key to writing programs that handle signals reliably is to keep close control of when signals can occur. In particular, you can simplify program logic if you avoid handling signals while main-line code is testing or modifying variables that are also accessed or modified by a signal handler.

Some of the ways you can use the library facilities to control when signals must be handled are discussed here. Note that these techniques, with the exception of the first one, are specific to the SAS/C library.

Signal Descriptions

This section provides a detailed description of each signal that can be handled by the SAS/C library, with the exception of SIGIO. (The SIGIO signal is not included because it currently has no special meaning for the SAS/C library.) Each description explains the information returned by a call to siginfo when a signal is generated naturally. When your program raises a signal by calling the raise function, a call to siginfo returns NULL except where noted otherwise. If the program raises a signal by calling siggen, siginfo returns the value of the second argument to siggen.

Note: The POSIX signals (SIGCHLD, SIGCONT, SIGHUP, SIGKILL, SIGPIPE, SIGQUIT, SIGSTOP, SIGTSTP, SIGTTIN, and SIGTTOU) are not included in this section because all pertinent information about them is contained in Tables 5.2 and 5.3 on pages 5-9 and 5-10, respectively. For general information about POSIX signal handling, refer to The POSIX.1 Standard: A Programmer's Guide.

SIGABND -- Program Abnormal Termination

The SIGABND signal is raised when the operating system terminates the C program with a system ABEND code. This ABEND either indicates a misuse of an operating system feature or an error by the system processing a valid request.

Default handling

By default, the signal causes abnormal termination of the program with the ABEND code requested by the operating system. If SIGABND results from a call to siggen, the ABEND code is taken from the ABRT_t structure passed to siggen.

Ignoring the signal

The SIGABND signal cannot be ignored. Similarly, a handler for SIGABND cannot return to the point of interrupt; an attempt to do so causes ABEND to be reissued.

Information returned by siginfo

If you call siginfo after a SIGABND signal occurs, siginfo returns a pointer to a structure of type ABND_t. This structure is defined as:
 typedef struct {
    unsigned ABEND_code;    /* ABEND code             */
    char *ABEND_str;        /* formatted ABEND code,  */
                            /* e.g., "B14", "U0240",  */
    void *ABEND_info;      /* OS SDWA, or CMS ABWSECT */
 } ABND_t;
 
The ABEND_code contains the unmodified system ABEND code. For example, after a system 106 ABEND, the ABEND_code value is 0x106. The ABEND_str is a null-terminated string giving a printable form of the ABEND code.

The ABEND_info pointer addresses an ABEND status block provided by the operating system, which gives the ABEND PSW, registers, and other such information. Under MVS, ABEND_str addresses an SDWA. Under CMS, it addresses an ABWSECT. For an ABEND issued by the SAS/C library, ABEND_info may be NULL.

Notes on defining a handler

A System ABEND in a C program is most likely to result from unexpected conditions in the C library. For example, the fopen function may ABEND if you attempt to open a file you are not authorized to access. If you provide a SIGTERM handler and use the longjmp function to continue program execution after such an ABEND, the library is not always able to clean up after the failure. This may prevent memory or other resources used by the library from being freed. For instance, after recovery from an ABEND in fopen, it may not be possible to open FOPEN_MAX files.

SIGABRT -- Program Abort

The SIGABRT signal is raised when the abort function is called or when a user ABEND occurs. SIGABRT may not be raised for an ABEND issued by the SAS/C library, depending on the severity of the problem.

Default handling

By default, SIGABRT causes abnormal program termination. If SIGABRT results from a call to abort or raise, the program is terminated with user ABEND code 1210. If SIGABRT results from a call to siggen, the ABEND code is taken from the ABRT_t structure passed to siggen.

Ignoring the signal

The SIGABRT signal cannot be ignored. Similarly, a handler for SIGABRT cannot return to the point of interrupt; an attempt to do so causes ABEND to be reissued.

Information returned by siginfo

If you call siginfo after a SIGABRT signal occurs, siginfo returns a pointer to a structure of type ABRT_t. This structure is defined as:
 typedef struct {
    unsigned ABEND_code;   /* ABEND code              */
    char *ABEND_str;       /* formatted ABEND code,   */
                           /* e.g., "B14", "U0240",   */
    void *ABEND_info;      /* OS SDWA, or CMS ABWSECT */
 } ABRT_t;
 
The ABEND_code is an integer from 0 through 4095 giving the ABEND code. The ABEND_str is a null-terminated string giving a printable form of the ABEND code.

The ABEND_info pointer addresses an ABEND status block provided by the operating system, which gives the ABEND PSW, registers, and other such information. Under MVS, ABEND_str addresses an SDWA. Under CMS, it addresses an ABWSECT. For an ABEND issued by the SAS/C library, ABEND_info may be NULL.

OpenEdition considerations

SAS/C uses SIGABRT to signal a user ABEND, including a library ABEND. This differs from OpenEdition, which expects every ABEND to be signaled by SIGABND.

SIGALRM -- Real-Time Expiration

SIGALRM is an asynchronous signal. The SIGALRM signal is raised when a time interval specified in a call to the alarm or alarmd function expires.

Because SIGALRM is an asynchronous signal, the SAS/C library discovers the signal only when you call a function, when a function returns, or when you issue a call to sigchk. For this reason and because of inaccuracies and overhead in operating system timing functions, you can consider the time interval requested by alarm a lower bound; the handler may not be invoked immediately after the interval expires.

Default handling

By default, SIGALRM causes the program to abnormally terminate with a user ABEND code of 1225.

Ignoring the signal

It is possible, but not particularly useful, to ignore SIGALRM.

Information returned by siginfo

When siginfo is called in a handler for SIGALRM, it returns NULL.

OpenEdition Considerations

If SIGALRM is managed by OpenEdition, the SAS/C alarmd and sleepd functions are not available. If the SAS/C library manages SIGALRM, the ps shell command will not accurately indicate when the process is sleeping.

SIGFPDIV -- Floating-Point Division by 0

The SIGFPDIV signal is raised when the second operand of the division operator (/) is 0, and default handling is in effect for SIGFPE. If you have specified a handler for SIGFPE (either SIG_IGN or a function you define), SIGFPDIV is not raised.

Default handling

If the SIGFPDIV signal is raised and default handling is in effect, the program abnormally terminates with an ABEND code of 0CF.

Ignoring the signal

If your program ignores SIGFPDIV, program execution continues, but the results of the failed expression are unpredictable.

Information returned by siginfo

If you call siginfo after a SIGFPDIV signal occurs, siginfo returns a pointer to a structure of type FPE_t. Refer to the description of SIGFPE for a discussion of this structure.

Notes on defining a handler

If you define a handler for SIGFPDIV, you can change the result of the computation by using the information returned by siginfo. Refer to the example in the description of the siginfo function for an illustration of this technique.

SIGFPE -- General Computational Error

The SIGFPE signal is raised when a computational error occurs. These errors include floating-point overflow, floating-point underflow, and either integer- or floating-point division by 0. Note that integer overflow never causes a signal; when integer overflow occurs, the result is reduced to 32 bits by discarding the most significant bits and is then interpreted as a signed integer.

Default handling

The default handling for SIGFPE is to raise a more specific signal for the SIGFPOFL, SIGFPUFL, SIGFPDIV, or SIGIDIV conditions. Handling of the more specific signal depends on whether a handler has been defined for it. Refer to the descriptions of each of these signals for more details.

Ignoring the signal

If your program ignores SIGFPE, the result of the computation that raises SIGFPE is undefined, unless the computation causes an underflow. For underflows, the result is set to 0.

Information returned by siginfo

If you call siginfo after a SIGFPE signal occurs, siginfo returns a pointer to a structure of type FPE_t. This structure is defined as:
 typedef struct {
    int int_code;       /* interrupt code                         */
    union {
       int *intv;       /* result for integer expression          */
       double *doublev; /* result for double expression           */
       } result;
    char *EPIE;         /* pointer to hardware program check info */
    double *fpregs;     /* floating-point register contents       */
    } FPE_t;
 
The int_code field contains the number of the more specific signal associated with the SIGFPOFL, SIGFPUFL, SIGFPDIV, or SIGIDIV conditions. The result field is a pointer to the result of the computation that raises the signal. If you want to continue processing, you can change the value that result points to.

The EPIE field is a pointer to a control block containing hardware information available at the time the signal occurs. (This information includes program status word and registers.) For information on the EPIE format, see IBM publication MVS/XA Supervisor Services and Macro Instructions. (Although an EPIE is provided only by the XA versions of the MVS and CMS operating systems, one is created by the run-time library for all MVS and CMS systems.)

The fpregs field is a pointer to an array of doubles that contains the contents of the floating-point registers at the time of the signal and stored in the order 0, 2, 4, 6.

Notes on defining a handler

If you define a handler for SIGFPE, you can determine what type of error caused the signal by testing the int_code field of the information returned by siginfo. You can also use this information to reset the result of the computation by changing the value that result points to. Refer to the example in the description of the siginfo function for an illustration of this technique.

OpenEdition Considerations

When SIGFPE is managed by OpenEdition, the default action for SIGFPE is abnormal process termination, and SIGFPE is never converted into another signal. If you want to handle one or more of the SIGFPDIV, SIGFPOFL, SIGFPUFL, or SIGIDIV signals specific to SAS/C, you must define SIGFPE as a signal managed by SAS/C.

SIGFPOFL -- Floating-Point Overflow

The SIGFPOFL signal is raised when the magnitude of the result of a floating-point computation exceeds the maximum supported by the hardware and default handling is in effect for SIGFPE. If you have specified a handler for SIGFPE (either SIG_IGN or a function you define), SIGFPOFL is not raised.

Default handling

If the SIGFPOFL signal is raised and default handling is in effect, the program abnormally terminates with an ABEND code of 0CC.

Ignoring the signal

If your program ignores SIGFPOFL, program execution continues, but the results of the failed expression are unpredictable.

Information returned by siginfo

If you call siginfo after a SIGFPOFL signal occurs, siginfo returns a pointer to a structure of type FPE_t. Refer to the description of SIGFPE for a discussion of this structure.

Notes on defining a handler

If you define a handler for SIGFPOFL, you can change the result of the computation by using the information returned by siginfo. Refer to the example in the description of the siginfo function for an illustration of this technique.

SIGFPUFL -- Floating-Point Underflow

The SIGFPUFL signal is raised when the magnitude of the nonzero result of a floating-point computation is smaller than the smallest nonzero floating-point value supported by the hardware and default handling is in effect for SIGFPE. If you specified a handler for SIGFPE (either SIG_IGN or a function you define), SIGFPUFL is not raised.

Default handling

If the SIGFPUFL signal is raised and default handling is in effect, the result of the computation that raised the signal is set to 0 and execution continues normally.

Ignoring the signal

If your program ignores SIGFPUFL, program execution continues, and the result of the computation that raised the signal is set to 0.

Information returned by siginfo

If you call siginfo after a SIGFPUFL signal occurs, siginfo returns a pointer to a structure of type FPE_t. Refer to the description of SIGFPE for a discussion of this structure.

Notes on defining a handler

If you define a handler for SIGFPUFL, you can change the result of the computation by using the information returned by siginfo. Refer to the example in the description of the siginfo function for an illustration of this technique.

Note: If a handler defined for SIGFPUFL does not change the value of the result, the result of the computation is undefined and it is not automatically set to 0.

SIGIDIV -- Integer Division by 0

The SIGIDIV signal is raised when the second operand of a division operator (/ or %) is 0 and default handling is in effect for SIGFPE. If you have specified a handler for SIGFPE (either SIG_IGN or a function you define), SIGIDIV is not raised.

Default handling

If the SIGIDIV signal is raised and default handling is in effect, the program abnormally terminates with an ABEND code of 0C9.

Ignoring the signal

If your program ignores SIGIDIV, program execution continues but the result of the computation that raised the signal is undefined.

Information returned by siginfo

If you call siginfo after a SIGIDIV signal occurs, siginfo returns a pointer to a structure of type FPE_t. Refer to the description of SIGFPE for a discussion of this structure.

Notes on defining a handler

If you define a handler for SIGIDIV, you can change the result of the computation by using the information returned by siginfo. Refer to the example in the description of the siginfo function for an illustration of this technique.

SIGILL -- Illegal Instruction

The SIGILL signal is raised when an attempt is made to execute an invalid, privileged, or ill-formed instruction. SIGILL is usually caused by a program error that overlays code with data or by a call to a function that is not linked into the program load module.

Default handling

By default, SIGILL causes program termination with an appropriate ABEND code (0C1 for an operation error, 0C2 for a privileged operation error, 0C3 for an execute error, or 0C6 for a specification error).

Ignoring the signal

The SIGILL signal cannot be ignored. If you code SIG_IGN as the second argument to signal, the call to signal is rejected.

Information returned by siginfo

If you call siginfo in a handler for SIGILL, siginfo returns a pointer to a structure of type ILL_t. This structure is defined as:
 typedef struct {
    int int_code;  /* interrupt code                         */
    char *EPIE;    /* pointer to hardware program check info */
    } ILL_t;
 
The int_code field of this structure contains the program code indicating what type of illegal instruction occurred. Refer to "Default handling" above.

The EPIE field is a pointer to a control block containing hardware information available at the time the signal occurred. (This information includes program status word and registers.) For information on the EPIE format, see IBM publication MVS/XA Supervisor Services and Macro Instructions. (Although an EPIE is provided only by the XA versions of the MVS and CMS operating systems, one is created by the run-time library for all MVS and CMS systems.)

Notes on defining a handler

If you define a handler for SIGILL, you can call siginfo and test the int_code field of the structure (returned by a call to siginfo) to determine what error occurred. Note that a handler for SIGILL cannot return to the point of interrupt; an attempt to do so causes the program to terminate as described in "Default handling" above.

SIGINT -- Interactive Terminal Attention Signal

SIGINT is an asynchronous signal. The SIGINT signal is raised when the terminal user requests a program interruption. Under MVS, the terminal PA1 or ATTN key raises the SIGINT signal; under CMS, the IC (Interrupt C) immediate command raises SIGINT. However, if you are executing the program using the debugger, you must use the debugger attn command to generate a SIGINT signal. (The PA1/ATTN key or the IC command is intercepted and handled by the debugger.) The debugger attn command is handled as if SIGINT were raised by the normal methods.

Default handling

The library does not perform any default actions for the SIGINT signal. If the program is executing under MVS, the PA1/ATTN key is handled by the program that invoked the C program (for example, ISPF or the TSO terminal monitor program). If the program is executing under CMS, the IC command is treated as an unknown command.

Ignoring the signal

Ignoring SIGINT by coding SIG_IGN as the second argument in the call to signal does not have the same effect as default handling. If SIGINT is ignored, use of the PA1/ATTN key or the IC command is recognized but it has no effect on the program.

Information returned by siginfo

When siginfo is called in a handler for SIGINT, it returns NULL.

Notes on defining a handler

Because SIGINT is an asynchronous signal, the library discovers the signal only when you call a function, when a function returns, or when you issue a call to sigchk. SIGINT frequently occurs while the program is reading from the terminal. If this occurs and the handler for SIGINT returns to the point at which the signal occurred, the input request is reissued, unless the handler set the error flag for the file.

SIGIUCV -- CMS Inter-User Communication

The SIGIUCV signal is raised as a result of communication between two VM users. The SIGIUCV signal can be generated only for programs that have used the iucvset function to initialize communication.

SIGIUCV is an asynchronous signal. For this reason, a handler for SIGIUCV can only be invoked when a function is called or returns, or when sigchk is used.

Default handling

By default, SIGIUCV causes the program to abnormally terminate with a user ABEND code of 1225. For this reason, you must have a SIGIUCV handler defined at all times that a signal can be discovered, if your program uses SIGIUCV.

Ignoring the signal

The SIGIUCV signal cannot be ignored. If you code SIG_IGN as the second argument to signal and an IUCV signal is received, the program terminates, as described in "Default handling" above.

Information returned by siginfo

If you call siginfo in a handler for SIGIUCV, it returns a pointer to a structure of one of several types, depending on the particular interrupt. This structure contains information about the communication that caused the signal. For example, if the signal indicates that a message has been sent by another user, you can call the iucvrecv function to obtain the message text. Refer to Chapter 5, "Inter-User Communications Vehicle (IUCV) Functions," in SAS/C Library Reference, Volume 2 for more information on what is returned by siginfo.

Notes on raising SIGIUCV

Use of raise or siggen with SIGIUCV has no effect on the status of any pending signals. Signals generated with raise are always synchronous; that is, they are never delayed, even if blocked, so an artificially generated SIGIUCV signal may be handled before any pending real SIGIUCV signals.

SIGMEM -- No Memory Available for Stack Space

The SIGMEM signal is raised when a function call requires additional stack space, but little space is available. At the start of program execution, 4K of stack space is reserved for emergency use; when no other space is available, the SIGMEM signal is raised. The reserved stack space is available to ensure that you can still execute a handler for the SIGMEM signal.

Note: If you use the =minimal run-time option to suppress stack overflow checking, the SIGMEM signal does not occur. In this case, if you run out of stack space, your program will probably ABEND as it tries to write past the end of the stack.

Default handling

The default handling for the SIGMEM signal is to ignore the condition. If the program can finish executing in the 4K of stack space reserved for emergency use, the program completes normally. If the program requires more than the emergency allocation, the program abnormally terminates with an 80A ABEND in MVS or a 0F7 in CMS.

Ignoring the signal

If your program ignores SIGMEM, processing proceeds as described in "Default handling" above.

Information returned by siginfo

If you call siginfo after a SIGMEM signal occurs, siginfo returns a pointer to an integer that contains the number of bytes required. This is only an approximation, and there is no guarantee that freeing this amount of memory will permit the failed allocation to succeed.

Notes on defining a handler

Because a SIGMEM handler is called when there is little memory available, you should avoid using any functions that require large amounts of memory. In particular, avoid opening files in a SIGMEM handler. You also should avoid output to stdout or stderr, unless these files have been used because these files are only partially open until they are first used. If you want to handle SIGMEM by writing an error message and terminating and you cannot guarantee that you have already used the diagnostic file, use longjmp to exit from the handler and write the message on completion of the jump. Termination of intermediate routines by longjmp may cause additional stack space to become available.

If the handler for SIGMEM returns to the point of interrupt, another attempt is made to allocate more stack space. If this attempt fails, the emergency allocation is used if less than 4K is required. If the emergency space is not sufficient, the program abnormally terminates.

After SIGMEM is raised during a program's execution, it is not raised again until one or more stack allocations have been successfully performed. This avoids the possibility of endless loops in which SIGMEM is raised repeatedly.

SIGSEGV -- Memory Access Violation

The SIGSEGV signal is raised when you attempt to illegally access or modify memory. SIGSEGV is usually caused by using uninitialized or NULL pointer values or by memory overlays.

Default handling

By default, SIGSEGV causes program termination with an appropriate ABEND code (0C4 for a protection error or 0C5 for an addressing error).

Ignoring the signal

The SIGSEGV signal cannot be ignored. If you code SIG_IGN as the second argument to signal, the call to signal is rejected.

Information returned by siginfo

If you call siginfo in a handler for SIGSEGV, siginfo returns a pointer to a structure of type SEGV_t. This structure is defined as:
 typedef struct {
    int int_code;  /* interrupt code                         */
    char *EPIE;    /* pointer to hardware program check info */
    } SEGV_t;
 
The fields in this structure are the same as those in the structure type ILL_t; refer to the description of SIGILL for details on this structure.

Notes on defining a handler

If you define a handler for SIGSEGV, you can call siginfo and test the int_code field of the structure (returned by a call to siginfo) to determine what error occurred. A handler for SIGSEGV cannot return to the point of interrupt; an attempt to do so causes the program to terminate, as described in "Default handling" above.

Note: If the program overlays library control blocks, the SIGSEGV signal may cause an immediate unrecoverable program ABEND, even when a signal handler has been defined.

SIGTERM -- Termination Request

The SIGTERM signal can only be generated by a call to either raise or siggen when SIGTERM is managed by SAS/C.

Default handling

By default, the signal causes abnormal termination of the program with a user ABEND code of 1225.

Ignoring the signal

If your program ignores SIGTERM, program execution proceeds.

Information returned by siginfo

When siginfo is called in a handler for SIGTERM, it returns NULL.

Copyright (c) 1998 SAS Institute Inc. Cary, NC, USA. All rights reserved.