Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: wordsmithing; reviewed

...

Noncompliant Code Example

In On nonpersistent platforms, this noncompliant code example contains a race window, starting when the host environment resets the signal and ending when the handler calls signal(). During that time, a second signal sent to the program will trigger the default signal behavior, consequently defeating the persistent behavior implied by the call to signal() from within the handler to reassert the binding.

If the environment is persistent (that is, it does not reset the handler when the signal is received), the signal() call from within the handler() is bound to signum: function is redundant.

Code Block
bgColor#ffcccc
langc
#include <signal.h>
 
void handler(int signum) {
  if (signal(signum, handler) == SIG_ERR) {
    /* Handle error */
  }
  /* Handle signal */
}
 
void func(void) {
  if (signal(SIGUSR1, handler) == SIG_ERR) {
    /* Handle error */
  }
}

On nonpersistent platforms, this solution contains a race window, starting when the host environment resets the signal and ending when the handler calls signal(). During that time, a second signal sent to the program will trigger the default signal behavior, consequently defeating the persistent behavior implied by the call to signal() from within the handler to reassert the binding.

...

Compliant Solution

For persistent platforms, calling the signal() function from within the signal handler to reassert the binding is unnecessary:

Code Block
bgColor#ccccff
langc
#include <signal.h>
 
void handler(int signum) {
  /* Handle signal */
}
 
void func(void) {
  if (signal(SIGUSR1, handler) == SIG_ERR) {
    /* Handle error */
  }
}

...

POSIX defines the sigaction() function, which assigns handlers to signals such as in a similar manner to signal() but also allows the caller to explicitly set persistence. Consequently, the sigaction() function can be used to eliminate the race window on nonpersistent operating systems.

...

POSIX recommends sigaction() and deprecates signal(). Unfortunately, sigaction() is not defined by the C -compliant Standard and is not supported on some platforms, including Windows.

...

There is no safe way to implement persistent signal-handler behavior on Windows platforms, and it should not be attempted. If a design depends on this behavior, and the design cannot be altered, it may be necessary to claim a deviation from the this rule after completing an appropriate risk analysis.

Exceptions

SIG34-EX1: On a machine For implementations with persistent signal handlers, it is safe for a handler to modify the behavior for of its own signal. Behavior modification would modifications include having ignoring the signal be ignored, reset resetting to the default behavior, or having the signal handled by a different handler. A handler assigning itself to its own signal is also safe because it is a no-op. Because multiple invocations of its signal will merely cause it to "interrupt itself," the handler is impervious to a race condition until it manages to reassign its signalreasserting it's binding is also safe but unnecessary.

The following code example resets a signal handler to the system's default behavior:

...

Two signals in quick succession can trigger the a race condition on nonpersistent platforms, causing the signal's default behavior despite a handler's attempt to override it.

...