13.13 <csignal>
The <csignal> header is the C++ version of the
standard C <signal.h> header. It declares
functions and macros related to signal handling.
A signal is a condition that can arise during
program execution. A signal can originate by an explicit call to
raise or abort, from external
sources (such as the user interrupting the program), or from internal
events (such as floating-point errors or memory violations). Each
signal has a handler, which is a function that
the C++ library calls when a signal occurs (called
raising the signal).
Signals are identified by integers. A program can establish different
handlers for different signal numbers. You can choose to ignore a
signal by using SIG_IGN as the signal handler. If
the signal is raised, no handler is called, and the program
continues. Each signal also has a default handler
(SIG_DFL). When a program starts, every signal
number is initialized with SIG_IGN or
SIG_DFL. The details are implementation-defined.
You can set your own handler for any signal by calling the
signal function. A handler is a function that
takes one parameter: the signal number. The signal handler function
is limited in what it can do. Unless a signal is raised by an
explicit call to raise or
abort, the only useful thing the handler can do is
to set a global flag. The type of the flag must be
sig_atomic_t.
The standard defines a basic set of signals, and an implementation is
free to define additional signals. On the other hand, an
implementation is not required to raise any signals. Remember that
arithmetic overflow, pointer violations, and the like result in
undefined behavior. (See Chapter 4.) Thus, an
implementation is free to terminate a program immediately, ignore the
error, raise a signal, or do anything else. Some signals are meant to
reflect external events, such as the user terminating the program.
How the user terminates a program is likewise implementation-defined.
Unix and Unix-like operating systems have much more extensive
signal-handling facilities. The <csignal>
handler as documented in this section is portable to all hosted C++
environments, regardless of operating system, although the portable
behavior is limited. Most uses of <csignal>
in real programs take advantage of additional, nonstandard
capabilities. Consult your compiler's and
library's documentation for details.
raise function |
Raises a signal
|
The raise function sends a signal to the running
program. The sig parameter is the signal number.
The return value is 0 for success or nonzero for
an error.
SIG_DFL macro |
Default handler
|
The SIG_DFL macro represents the default handling
of a signal. The macro expands to a constant whose value is suitable
as the second argument to the signal function.
SIG_ERR macro |
Error return
|
The SIG_ERR macro represents the value returned
from signal in the event of an error. It expands
to a constant expression.
SIG_IGN macro |
Ignore signal
|
The SIG_IGN macro tells signal
to ignore a signal. The macro expands to a constant whose value is
suitable as the second argument to the signal
function.
SIGABRT macro |
Abort signal number
|
The SIGABRT macro expands to a positive integer
constant that represents an abnormal termination. The abort function
raises SIGABRT.
SIGFPE macro |
Floating-point error signal number
|
The SIGFPE macro expands to a positive integer
constant that represents a floating-point exception, such as division
by zero. An implementation is not required to raise
SIGFPE for a floating-point error.
SIGILL macro |
Illegal instruction signal number
|
The SIGILL macro expands to a positive integer
constant that represents an illegal instruction.
SIGINT macro |
User interrupt signal number
|
The SIGINT macro expands to a positive integer
constant that represents a user interrupt.
SIGSEGV macro |
Segmentation violation signal number
|
The SIGSEGV macro expands to a positive integer
constant that represents an addressing fault (segmentation
violation).
SIGTERM macro |
Terminate signal number
|
Description
The SIGTERM macro expands to a positive integer
constant that represents a request to terminate the program.
sig_atomic_t type |
Atomic type
|
typedef ... sig_atomic_t;
|
|
The sig_atomic_t type is an integral type that can
be accessed atomically—that is, even if a signal is delivered,
the entire value is read or written. The actual type is
implementation-defined.
signal function |
Sets a signal handler
|
void (*signal(int sig, void (*func)(int)))(int);
|
|
The signal function controls the
program's behavior when a signal is delivered to the
program. The first parameter (sig) is the signal
number. The second parameter (func) is the
function to call when signal sig is delivered.
The func parameter can also be one of the special
values SIG_DFL or SIG_IGN. Use
SIG_DFL to get the default behavior; use
SIG_IGN to ignore a signal.
The default behavior for a signal is implementation-defined, but it
usually results in the termination of the program. The signal handler
must not use any C++ features (such as throwing an exception), or the
results will be implementation-defined. The function must have
"C" linkage.
If the func parameter is a function pointer, that
function is called when signal sig is delivered.
Unless the signal is delivered by calling abort or
raise, the function is highly restricted in what
it can do:
The handler must not call any function in the standard library except
signal, and the first parameter must be
sig.
The handler must not refer to any variable with static storage except
it can assign a value to a variable of type
volatile sig_atomic_t.
If the signal is the result of a computational error such as
SIGFPE, the signal handler must not return, but
should call abort or exit.
(Yes, this item contradicts the first item.)
|
Real implementations have looser restrictions, such as allowing calls
to other library functions from a signal handler. The library
functions that are permitted varies, but every practical
implementation allows at least abort. If you must
use signal handlers in your program, you will probably need to rely
on behavior that is dictated by your host environment, extending the
limitations of the C++ standard.
|
|
If the handler returns normally, and the signal is not the result of
a computational error, execution continues from the point where it
was interrupted.
The return value of signal is the previous value
of the signal handler for sig, or
SIG_ERR for an error. If
SIG_ERR is returned, errno is
set.
Example 13-7 shows a simple signal handler that sets
a global flag when the user interrupts the program. Until the user
interrupts it, the program reads input and counts the number of lines
the user typed.
Example
Example 13-7. Reading input until the program is interrupted
#include <csignal>
#include <iostream>
#include <string>
volatile std::sig_atomic_t interrupted;
// Signal handler sets a global flag
extern "C" void sigint(int sig)
{
interrupted = 1;
}
int main( )
{
//
if (std::signal(SIGINT, sigint) == SIG_ERR)
std::cerr << "Cannot set signal handler\n";
else
{
unsigned long count = 0; // Count lines.
while(! interrupted)
{
std::cout << "> "; // User prompt
std::string s;
if (! std::getline(std::cin, s))
// EOF does not terminate the loop; only SIGINT does this.
std::cin.clear( );
++count;
}
std::cout << "I counted " << count << " line(s).\n";
}
}
|