Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

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
bgColor#FFcccc
#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

...