![]() Chapter Contents  | 
![]() Previous  | 
![]() Next  | 
| Signal-Handling Functions | 
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
USS. 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:
signal
or 
sigaction
 functions to identify a handler
for the signal in the beginning of the program or at some point before the
signal may occur.
signal
 within the handler function to reinstate handling for
that signal.
(This is not necessary when a handler is defined using 
sigaction
).
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:
sigemptyset
, 
sigfillset
, 
sigaddset
, 
sigdelset
, and 
sigismember
 functions as required to define a
signal mask that will block signals while the handler is running.
sigaction
 function to identify a handler for the signal at the beginning of
the program or at some point before the signal may occur.
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.
 USS 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 USS 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.  ![[cautionend]](../common/images/cautend.gif)
SAS/C uses the signal 
SIGABRT
 to represent user ABENDs including library ABENDs.  This is different
from USS, 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, USS reports the status of an ABEND
as terminated by 
SIGKILL
 
rather than as terminated by 
SIGABND
.  ![[cautionend]](../common/images/cautend.gif)
| 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
. Summary of Information from siginfo summarizes the information returned by 
siginfo
.
Note:   
siginfo
is not a standard C function; avoid using it in programs that must be portable.  ![[cautionend]](../common/images/cautend.gif)
The return value of 
siginfo
 is always 0 for any signal managed by USS,
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 Summary of Default Actions.
| 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 USS, 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.
Summary of Ignoring Signals lists which signals can be ignored. For more information, refer to the descriptions of the signals.
![]() Chapter Contents  | 
![]() Previous  | 
![]() Next  | 
![]() Top of Page  | 
Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.