You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 15 Next »

The signal() function behaves differently in Windows than it does on Linux/BSD systems. When a signal handler is installed with the signal() function in Windows, the default action is restored for that signal after the signal is triggered. Conversely, Linux/BSD systems leave the signal handler defined by the user in place until it is explicitly removed.

#include <stdio.h>
#include <signal.h>

volatile sig_atomic_t e_flag = 0;

void handler(int signum) {
  e_flag = 1;
}

int main(void) {
  signal(SIGINT, handler);
  while(!e_flag) {}
  puts("Escaped from first while()");
  e_flag = 0;
  while(!e_flag) {}
  puts("Escaped from second while()");
  return 0;
}

*nix systems automatically reinstall signal handlers upon handler execution. For example, when compiled with gcc 3.4.4 and executed under Red Hat Linux, the SIGINT is captured both times by handler.

% ./SIG01-A
^C
Escaped from first while()
^C
Escaped from second while()
%

However, under Windows systems signal handlers are not automatically reinstalled. For example, when compiled with Microsoft Visual Studio 2005 version 8.0, only the first SIGINT is captured by handler.

> SIG01-A.exe
^C
Escaped from first while()
^C
>

The second SIGINT executes the default action, which is to terminate program execution.

Different actions must be taken depending on whether or not you desire signal handlers to be persistent.

Persistent handlers

By default, *nix systems leave the handler in place after a signal is generated, whereas Windows system do not.

Non-Compliant Code Example (Windows)

This non-complaint code example fails to persist the signal handler on Windows platforms.

void handler(int signum) {
  /* handling code */
}

Compliant Solution (Windows)

A C99-compliant solution to persist the handler on a Windows system is to rebind the signal to the handler in the first line of the handler itself.

void handler(int signum) {
#ifdef WINDOWS
  signal(signum, handler);
#endif
  /* handling code */
}

Non-persistent handlers

By default, Windows systems reset the signal handler to its default action after a signal is generated, whereas *nix system do not.

Non-Compliant Code Example (*nix)

This non-complaint code example fails to reset the signal handler to its default behavior on *nix systems.

void handler(int signum) {
  /* handling code */
}

Compliant Solution (*nix)

A C99-compliant solution to reset the handler on a *nix system is to rebind the signal to the implementation-defined default handler in the first line of the handler itself.

void handler(int signum) {
#ifdef WINDOWS
  /* windows automatically resets handlers to default */
#else
  signal(signum, SIG_DFL);
#endif
  /* handling code */
}

Risk Analysis

Failure to understand implementation-specific details regarding signal handler persistence can lead to unexpected behavior.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

SIG01-A

1 (high)

1 (likely)

3 (low)

P3

L3

References

[[ISO/IEC 9899-1999TR2]] Section 7.14.1.1, "The signal function"

  • No labels