...
When a signal occurs, the normal flow of control of a program is interrupted. If a signal occurs that is being trapped by a signal handler, that handler is invoked. When it is finished, execution continues at the point at which the signal occurred. This arrangement could cause problems if the signal handler invokes a library function that was being executed at the time of the signal. Since library functions are not guaranteed to be reentrant, they should not be called from a signal handler that returns.
Wiki Markup |
---|
Similarly, Section 7.14.1 paragraph 5 of C99 \[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\] states that |
...
In this non-compliant code example, storage is dynamically allocated to hold a copy of a string. A string literal is copied into the allocated memory, which is then printed and the memory freed. The program also registers the signal handler int_handler()
to handle the terminal interrupt signal SIGINT
, which also . The int_handler()
function calls free()
then exits.
Code Block | ||
---|---|---|
| ||
#include <signal.h> char *foo; void int_handler() { free(foo); _Exit(0); } int main(void) { foo = (char *)malloc(sizeof("Hello World.")); if (foo == NULL) { /* handle error condition */ } signal(SIGINT, int_handler); strcpy(foo, "Hello World."); puts(foo); free(foo); return 0; } |
This program has two three potential problems. The first is that the free()
function is not asynchronous-safe, and its invocation from within a signal handler is a violation of this rule. If an interrupt signal is received during the free()
call in main()
, the heap may be corrupted.
The second problem is if SIGINT
occurs after the call to free()
, resulting in the memory referenced by foo()
being freed twice. This is a violation of MEM31-C. Free dynamically allocated memory exactly once and SIG31-C. Do not access or modify shared objects in signal handlers.
The third problem is that the signal handler reads the variable foo
, which is not declared to be of type volatile sig_atomic_t
. This is also a violation of SIG31-C. Do not access or modify shared objects in signal handlers.
The _Exit()
function called from within the int_handler()
signal handler causes immediate program termination and is asynchronous-safe, whereas exit()
may call cleanup routines first, and consequently is not asynchronous-safe. If it is important that your application invoke handlers registered by the atexit()
function to perform cleanup actions before exiting, you may wish to set a flag (of type volatile sig_atomic_t
) from the signal handler indicating the program should exit and return (see ERR04-A. Choose an appropriate termination strategy).
Implementation Details
POSIX
...