Versions Compared

Key

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

No direct issues come from this, but you need to be careful that something doesn't generate two similar signals that call the same handler, and your code to deal with it get executed twice.

According to the "Signals and Interrupts" section of the C99 Rationale:

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.

And according to the OpenBSD signal() man page

The following functions are either reentrant or not interruptible by sig-
nals and are asyncronous-signal safe. Therefore applications may invoke
them, without restriction, from signal-catching functions:

Base Interfaces:

_exit(), access(), alarm(), cfgetispeed(), cfgetospeed(), cfsetispeed(),
cfsetospeed(), chdir(), chmod(), chown(), close(), creat(), dup(),
dup2(), execle(), execve(), fcntl(), fork(), fpathconf(), fstat(),
fsync(), getegid(), geteuid(), getgid(), getgroups(), getpgrp(),
getpid(), getppid(), getuid(), kill(), link(), lseek(), mkdir(),
mkfifo(), open(), pathconf(), pause(), pipe(), raise(), read(), rename(),
rmdir(), setgid(), setpgid(), setsid(), setuid(), sigaction(),
sigaddset(), sigdelset(), sigemptyset(), sigfillset(), sigismember(),
signal(), sigpending(), sigprocmask(), sigsuspend(), sleep(), stat(),
sysconf(), tcdrain(), tcflow(), tcflush(), tcgetattr(), tcgetpgrp(),
tcsendbreak(), tcsetattr(), tcsetpgrp(), time(), times(), umask(),
uname(), unlink(), utime(), wait(), waitpid(), write().

Non-Compliant Coding Example

Code Block
bgColor#FFcccc
#include <signal.h> 
 
char *global_ptr; 
 
void handler() { 
  free(global_ptr); 
  _exit(0);
} 
 
int main() { 
  global_ptr = malloc(16);

  signal(SIGINT, handler); 
  signal(SIGTERM, handler);
 
  /* program code */

  return 0;
}

Compliant Solution

Signal handlers should be as minimal as possible, only unconditionally setting a flag where appropriate, and returning.

#include <setjmp.h> #include <signal.h> static jmp_buf env; int interrupted = 0; void int_handler() { interrupted = 1; } int main() { char *foo; signal(SIGINT, int_handler); foo = malloc(15); foo = "Nothing yet."; /* main loop which displays foo */ if(interrupt == 1) { foo = "Signal caught."; } return 0; }
Code Block
bgColor#ccccff

Risk Assessment

Depending on the code, this could lead to any number of attacks, many of which could give root access. For an overview of some software vulnerabilities, see Zalewski's signal article.

...