signal

Description

Sets interrupt signal handling.

#include <signal.h>

void ( __cdecl *signal( int sig, void( __cdecl *func )
( int sig[[, int subcode]] ) ) ) ( int sig );

sig Signal value  
func Function to be executed  
subcode Optional subcode to the signal number  

Remarks

The signal function allows a process to choose one of several ways to handle an interrupt signal from the operating system.

The sig argument must be one of the manifest constants described in Table R.13 and defined in SIGNAL.H.

Table R.13 Signals and Responses

Value Mode Meaning Default Action

SIGABRT Real Abnormal termination Terminates the calling program with exit code 3
SIGFPE Real Floating-point error Terminates the calling program with exit code 3
SIGILL Real Illegal instruction Terminates the calling program with exit code 3
SIGINT Real CTRL+C signal Terminates the calling program with exit code 3
SIGSEGV Real Illegal storage access Terminates the calling program with exit code 3
SIGTERM Real Termination request Terminates the calling program with exit code 3

Note that SIGILL, SIGSEGV, and SIGTERM are not generated with DOS. They are included for ANSI compatibility. Thus, you can set signal handlers for these signals via signal, and you can also explicitly generate these signals by calling raise.

Note also that signal settings are not preserved in child processes created by calls to _exec or _spawn. The signal settings are reset to the default in the child process.

The action taken when the interrupt signal is received depends on the value of func. The func argument must be either a function address or one of the manifest constants defined in SIGNAL.H and listed below:

SIG_DFL

Uses system-default response. The system-default response for all signals is to abort the calling program. The calling process is terminated with exit code 3, and control returns to DOS. If the calling program uses stream I/O, buffers created by the run-time library are not flushed, but buffers created by the operating system are flushed.

SIG_IGN

Ignores interrupt signal. This value should never be given for SIGFPE, since the floating-point state of the process is left undefined.

Function address

Installs the specified function as the handler for the given signal.

For all signals except SIGFPE, the function is passed the sig argument SIGINT and executed.

For SIGFPE signals, the function is passed two arguments; namely SIGFPE and the floating-point error code identifying the type of exception that occurred.

For SIGFPE, the function pointed to by func is passed two arguments, SIGFPE and an integer error subcode, FPE_xxx; then the function is executed. (See the include file FLOAT.H for definitions of the FPE_xxx subcodes.) The value of func is not reset upon receiving the signal. In C programs, SIGFPE is the only constant available when the _WINDOWS constant is defined. The _WINDOWS constant is defined by CL options /GA, /GD, /GE, /GW, and /Gw. To recover from floating-point exceptions, use setjmp in conjunction with longjmp. (See the example under _fpreset.) If the function returns, the calling process resumes execution with the floating-point state of the process left undefined.

If the function returns, the calling process resumes execution immediately following the point at which it received the interrupt signal. This is true regardless of the type of signal or operating mode.

Before the specified function is executed with DOS versions 3.x or earlier, the value of func is set to SIG_DFL. The next interrupt signal is treated as described above for SIG_DFL, unless an intervening call to signal specifies otherwise. This allows the program to reset signals in the called function.

Since signal-handler routines are normally called asynchronously when an interrupt occurs, it is possible that your signal-handler function will get control when a run-time operation is incomplete and in an unknown state. Certain restrictions therefore apply to the functions that can be used in your signal-handler routine:

1.Do not issue low-level or standard input and output routines (e.g., printf, _read, _write, fread).

2.Do not call heap routines or any routine that uses the heap routines (e.g., malloc, _strdup, _putenv).

3.Do not use any function that generates a system call (e.g., _getcwd, time).

4.Do not use the longjmp function unless the interrupt is caused by a floating-point exception (i.e., sig is SIGFPE). In this case, the program should first reinitialize the floating-point package by means of a call to _fpreset.

5.Do not use any overlay routines.

Note:

With DOS, a program must contain floating-point code if it is to trap the SIGFPE exception with the signal function. If your program does not have floating-point code and it requires the run-time library's signal-handling code, simply declare a volatile double and initialize it to zero:

volatile double d = 0.0f;

Return Value

The signal function returns the previous value of func associated with the given signal. For example, if the previous value of func was SIG_IGN, the return value will be SIG_IGN.

A return value of SIG_ERR indicates an error, and errno is set to EINVAL.

Compatibility

Standards:ANSI, UNIX

16-Bit:DOS, QWIN, WIN, WIN DLL

32-Bit:DOS32X

See Also

abort, _exec functions, exit, _exit, _fpreset, _spawn functions

Example

/* SIGNAL.C illustrates setting up signal interrupt routines. Functions

* illustrated include signal and raise.

*

* Since C I/O functions are not safe inside signal routines, the code

* uses conditionals to use system-level DOS services. Another option

* is to set global flags and do any I/O operations outside the

* signal handler.

*/

#include <stdio.h>

#include <conio.h>

#include <signal.h>

#include <process.h>

#include <stdlib.h>

#include <dos.h>

#include <bios.h>

void ctrlchandler( int sig ); /* Prototypes */

void safeout( char *str );

int safein( void );

void main( void )

{

int ch;

/* Install signal handler to modify CTRL+C behavior. */

if( signal( SIGINT, ctrlchandler ) == SIG_ERR )

{

fprintf( stderr, "Couldn't set SIGINT\n" );

abort();

}

/* Loop prints message to screen asking user to

* enter Cntl+C--at which point the ctrlchandler

* signal handler takes control.

*/

do

{

printf( "Press Ctrl+C to enter handler.\n" );

}

while( ch = _getch()); /* Discard keystokes */

}

/* A signal handler must take a single argument. The argument can be

* tested within the handler and thus allows a single signal handler

* to handle several different signals. In this case, the parameter

* is included to keep the compiler from generating a warning but is

* ignored because this signal handler only handles one interrupt:

* SIGINT (Ctrl+C).

*/

void ctrlchandler( int sig )

{

int c;

char str[] = " ";

/* Disallow CTRL+C during handler. */

signal( SIGINT, SIG_IGN );

safeout( "User break - abort processing (y|n)? " );

c = safein();

str[0] = c;

// safeout( str );

safeout( "\r\n" );

if( (c == 'y') || (c == 'Y') )

abort();

else

{

/* The CTRL+C interrupt must be reset to our handler since

* by default it is reset to the system handler.

*/

signal( SIGINT, ctrlchandler );

safeout( "Press Ctrl+C to enter handler.\r\n" );

}

}

/* Outputs a string using system level calls. */

void safeout( char *str )

{

union _REGS inregs, outregs;

inregs.h.ah = 0x0e;

while( *str )

{

inregs.h.al = *str++;

_int86( 0x10, &inregs, &outregs );

}

}

/* Inputs a character using system level calls. */

int safein()

{

return _bios_keybrd( _KEYBRD_READ ) & 0xff;

}

Output

Press Ctrl+C to enter handler.

^C

User break - abort processing (y|n)? y

abnormal program termination