signal() — Handle interrupts

Standards

Standards / Extensions C or C++ Dependencies
ISO C
POSIX.1
POSIX.4a
XPG4
XPG4.2
C99
Single UNIX Specification, Version 3
both  

Format

#include <signal.h>

void(*signal(int sig, void(*func)(int)))(int);

General description

Allows a process to choose one of several ways to handle an interrupt signal sig from the operating system or from the raise() function.

The sig argument must be one of the macros defined in the signal.h header file. See Table 1.

The func argument must be one of the macros, SIG_DFL or SIG_IGN, defined in the signal.h header file, or a function address.

If the value of func is SIG_DFL, default handling for that signal will occur. If the value of func is SIG_IGN, the signal will be ignored. Otherwise, func points to a function to be called when that signal occurs. Such a function is called a signal handler.

When a signal occurs, if func points to a function:
  1. First the equivalent of signal(sig,SIG_DFL); is executed or an implementation-defined blocking of the system is performed. (If the value of sig is SIGILL, the occurrence of the reset to SIG_DFL is implementation-defined.)
  2. Next, the equivalent of (*func)(sig); is executed. The function func may terminate by executing a return statement or by calling the abort(), exit(), or longjmp() function. If func executes a return statement and the value of sig was SIGFPE or any other implementation-defined value corresponding to a computational exception, the behavior is undefined. Otherwise, the program will resume execution at the point it was interrupted.

If a signal occurs for a reason other than having called the abort() or raise() function, the behavior is undefined if the signal handler calls any function in the standard library other than the signal() function itself (with a first argument of the signal number corresponding to the signal that caused the invocation of the handler). Behavior is also undefined if the signal handler refers to any object with static storage duration other than by assigning a value to a static storage duration variable of type volatile sig_atomic_t. Furthermore, if such a call to the signal() function returns SIG_ERR, the value of errno is indeterminate.

At program startup, the equivalent of signal(sig, SIG_IGN); may be executed for some selected signals. The equivalent of signal(sig, SIG_DFL); is executed for all other signals.

The action taken when the interrupt signal is received depends on the value of func.
Value
Meaning
SIG_DFL
Default handling for the signal will occur.
SIG_IGN
The signal is to be ignored.
As of Language Environment® Release 3, the defaults for SIGUSR1, SIGUSR2, SIGINT, and SIGTERM are changed from the signal being ignored to abnormal termination. To compensate for this change, you would explicitly register that the signal is to be ignored, using a call sequence such as:
signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, SIG_IGN);
signal(SIGINT,  SIG_IGN);
signal(SIGTERM, SIG_IGN);

These calls may be made either in the source or they can be made from the HLL user exit CEEBINT, which will require a re-link.

Special behavior for POSIX: For a z/OS® UNIX C application running POSIX(ON), the interrupt signal can also come from kill() or from another process. A program can use sigaction() to establish a signal handler; sigaction() blocks the signal while the signal handler has control. If you use signal() to establish a signal handler, the signal reverts back to the default action. If you want the signal handler to get control for the next signal of this type, you must reissue signal().

signal(sig, func) is equivalent to sigaction(sig, &act, NULL), where act points to a sigaction structure containing an sa_action of func, an sa_mask by sigemptyset(), and an sa_flags containing _SA_OLD_STYLE.

Note: The sigaction() function supersedes the signal() interface, and should be the preferred usage. In particular, sigaction() and signal() must not be used in the same process to control the same signal.

For a list of considerations for coding signal-catching functions that will support asynchronous signals, refer to sigaction() — Examine or change a signal action.

The sig argument must be one of the macros defined in the signal.h header file.

Special behavior for C++:
  • The behavior when mixing signal-handling with C++ exception handling is undefined. Also, the use of signal-handling with constructors and destructors is undefined.
  • C++ and C language linkage conventions are incompatible, and therefore signal() cannot receive C++ function pointers. If you attempt to pass a C++ function pointer to signal(), the compiler will flag it as an error. Therefore, to use the signal() function in the C++ language, you must ensure that signal handler routines established have C linkage, by declaring them as extern "C".

The signals supported are listed below.

Table 1. Signals Supported by C or C++ — POSIX(OFF)
Value Default Action Meaning
SIGABND 1 Abend
SIGABRT 1 Abnormal termination (sent by abort())
SIGFPE 1 Arithmetic exceptions that are not masked, for example, overflow, division by zero, and incorrect operation
SIGILL 1 Detection of an incorrect function image
SIGINT 1 Interactive attention
SIGSEGV 1 Incorrect access to memory
SIGTERM 1 Termination request sent to the program
SIGUSR1 1 Intended for use by user applications
SIGUSR2 1 Intended for use by user applications
SIGIOERR 2 A serious I/O error was detected.
In Table 1, the Default Actions are:
1
Normal termination of the process.
2
Ignore the signal.

When the runtime option POSIX(ON) is specified, if a signal catcher for a SIGABND, SIGFPE, SIGILL or SIGSEGV signal runs as a result of a program check or an ABEND, and the signal catcher executes a RETURN statement, the process will be terminated.

Returned value

If successful, signal() returns the most recent value of func.

If unsuccessful, signal() returns a value of SIG_ERR and a positive value in errno.

There are no documented errno values. If an error occurs, issue perror() using the errno value.

Example

CELEBS20
/* CELEBS20                                      

   This example shows you how to establish a signal handler.                    

 */                                                                             
#include <signal.h>                                                             
#include <stdio.h>                                                              
#include <stdlib.h>                                                             
#define  ONE_K  1024                                                            
                                                                                
#define OUT_OF_STORAGE       (SIGUSR1)                                          
                                                                                
/* The SIGNAL macro does a signal() checking the return code */                 
#define SIGNAL(handler, StrCln)       {                \                        
  if (signal((handler), (StrCln)) == SIG_ERR) {        \                        
    perror("Could not signal user signal");            \                        
    abort();                                           \                        
  }                                                    \                        
}                                                                               
                                                                                
#ifdef __cplusplus                 /* the __cplusplus macro       */            
extern "C" void StrCln(int);       /* is automatically defined    */            
#else                              /* by the C++/MVS compiler     */            
void StrCln(int);                                                               
#endif                                                                          
                                                                                
void DoWork(char **, int);                                                      
                                                                                
int main(int argc, char *argv[]) {                                              
  int size;                                                                     
  char *buffer;                                                                 
                                                                                
  signal(OUT_OF_STORAGE, StrCln);                                               
                                                                                
  if (argc != 2) {                                                              
    printf("Syntax: %s size \n", argv[0]);                                      
    return(-1);                                                                 
  }                                                                             
                                                                                
  size = atoi(argv[1]);                                                         
                                                                                
  DoWork(&buffer, size);                                                        
  return(0);                                                                    
}                                                                               
                                                                                
void StrCln(int SIG_TYPE) {                                                     
  printf("Failed trying to malloc storage\n");                                  
  signal(SIG_TYPE, SIG_DFL);                                                    
  exit(0);                                                                      
}                                                                               
                                                                                
void DoWork(char **buffer, int size) {                                          
  int rc;                                                                       
                                                                                
  while (*buffer !=NULL)                                                        
    *buffer = (char *)malloc(size*ONE_K);                                       
  if (*buffer == NULL) {                                                        
     if (raise(OUT_OF_STORAGE)) {                                               
        perror("Could not raise user signal");                                  
        abort();                                                                
     }                                                                          
  }                                                                             
  return;                                                                       
}                                                                               

Related information