Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Updated the list of POSIX async-safe functions, made other minor edits; reviewed

Call only asynchronous-safe functions within signal handlers. For strictly conforming programs, only the C standard library functions abort(), _Exit(), quick_exit(), and signal() can be called from within a signal handler. 

Subclause 7.14.1.1, paragraph 5, of the C Standard [ISO/IEC 9899:2011] states that if the signal occurs other than as the result of calling the abort() or raise() function, the behavior is undefined if

...the signal handler calls any function in the standard library other than the abort function function, the _Exit function function, the quick_exit function, or the signal function function with the first argument equal to the signal number corresponding to the signal that caused the invocation of the handler. 

Many systems define an implementation-specific list of asynchronous-safe functions. These functions can also be called within a signal handler. This restriction applies to library functions as well as application-defined functions.

...

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 can cause problems if the signal handler invokes a library function that was being executed at the time of the signal.

In general, I/O functions are not safe to invoke inside signal handlers. Check your system's asynchronous-safe functions before using them in signal handlers.

Noncompliant Code Example

In this noncompliant example, the C standard library function fprintf() is called from the signal handler via the function log_message(). The function free() is also not asynchronous-safe, and its invocation from within a signal handler is also a violation of this rule.

...

Code Block
bgColor#ffcccc
langc
#include <signal.h>
#include <stdlib.h>
 
void term_handler(int signum) {
  /* SIGTERM handling specific */
}
 
void int_handler(int signum) {
  /* SIGINT handling specific */
  if (raise(SIGTERM) != 0) {
    /* Handle error */
  }
}
 
int main(void) {
  if (signal(SIGTERM, term_handler) == SIG_ERR) {
    /* Handle error */
  }
  if (signal(SIGINT, int_handler) == SIG_ERR) {
    /* Handle error */
  }
 
  /* Program code */
  if (raise(SIGINT) != 0) {
    /* Handle error */
  }
  /* More code */
 
  return EXIT_SUCCESS;
}

...

In this compliant solution, the call to the raise() function inside handler() is replaced by a direct call to log_msg()the functionality that was in the term handler:

Code Block
bgColor#ccccff
langc
#include <signal.h>
 
void logterm_msghandler(int signum) {
  /* LogSIGTERM errorhandling message in some asynchronous-safe manner specific */
}
 
void int_handler(int signum) {
  /* DoSIGINT some handling specific */
  /* Pass control to the term SIGINThandler */
  logterm_msghandler(SIGUSR1SIGTERM);
}
 
int main(void) {
  if (signal(SIGUSR1SIGTERM, logterm_msghandler) == SIG_ERR) {
    /* Handle error */
  }
  if (signal(SIGINT, int_handler) == SIG_ERR) {
    /* Handle error */
  }
 
  /* Program code */
  if (raise(SIGINT) != 0) {
    /* Handle error */
  }
  /* More code */
 
  return 0EXIT_SUCCESS;
}

Noncompliant Code Example (POSIX)

...

POSIX

The following table from the Open Group Base Specifications [Open Group 2004the POSIX standard [IEEE Std 1003.1:2013] defines a set of functions that are asynchronous-signal-safe. Applications may invoke these functions, without restriction, from a signal handler.

Asynchronous-Signal-Safe Functions 

_Exit()

_exitfexecve()

abortposix_trace_event()

acceptsigprocmask()

_exit()

fork()

pselect()

sigqueue()

abort()

fstat()

pthread_kill()

sigset()

accept()

fstatat()

pthread_self()

sigsuspend()

access()

fsync()

pthread_sigmask()

sleepaccess()

aio_error()

ftruncate()

raise()

sockatmark()

aio_return()

futimens()

read()

socket()

aio_suspend()

alarmgetegid()

bindreadlink()

cfgetispeedsocketpair()

cfgetospeedalarm()

cfsetispeedgeteuid()

cfsetospeedreadlinkat()

chdirstat()

chmodbind()

chowngetgid()

clock_gettimerecv()

closesymlink()

connectcfgetispeed()

creatgetgroups()

duprecvfrom()

dup2symlinkat()

execlecfgetospeed()

execvegetpeername()

fchmodrecvmsg()

fchowntcdrain()

fcntlcfsetispeed()

fdatasyncgetpgrp()

forkrename()

fpathconftcflow()

fstatcfsetospeed()

fsyncgetpid()

ftruncaterenameat()

getegidtcflush()

geteuidchdir()

getgidgetppid()

getgroupsrmdir()

getpeernametcgetattr()

getpgrpchmod()

getpidgetsockname()

getppidselect()

getsocknametcgetpgrp()

getsockoptchown()

getuidgetsockopt()

killsem_post()

linktcsendbreak()

listenclock_gettime()

lseekgetuid()

lstatsend()

mkdirtcsetattr()

mkfifoclose()

openkill()

pathconfsendmsg()

pausetcsetpgrp()

pipeconnect()

polllink()

posix_trace_eventsendto()

pselecttime()

raisecreat()

readlinkat()

readlinksetgid()

recvtimer_getoverrun()

recvfromdup()

recvmsglisten()

renamesetpgid()

rmdirtimer_gettime()

selectdup2()

sem_postlseek()

sendsetsid()

sendmsgtimer_settime()

sendtoexecl()

setgidlstat()

setpgidsetsockopt()

setsidtimes()

setsockoptexecle()

setuidmkdir()

shutdownsetuid()

sigactionumask()

sigaddsetexecv()

sigdelsetmkdirat()

sigemptysetshutdown()

sigfillsetuname()

sigismemberexecve()

sleepmkfifo()

signalsigaction()

sigpauseunlink()

sigpendingfaccessat()

sigprocmaskmkfifoat()

sigqueuesigaddset()

sigsetunlinkat()

sigsuspendfchdir()

sockatmarkmknod()

socketsigdelset()

socketpairutime()

statfchmod()

symlinkmknodat()

sysconfsigemptyset()

tcdrainutimensat()

tcflowfchmodat()

tcflushopen()

tcgetattrsigfillset()

tcgetpgrputimes()

tcsendbreakfchown()

tcsetattropenat()

tcsetpgrpsigismember()

timewait()

timer_getoverrunfchownat()

timer_gettimepause()

timer_settimesignal()

timeswaitpid()

umaskfcntl()

unamepipe()

unlinksigpause()

utimewrite()

waitfdatasync()

waitpidpoll()

writesigpending()

 

 

All functions not listed in this table are considered to be unsafe with respect to signals. In the presence of signals, all functions defined by Standard for Information Technology—Portable Operating System Interface (POSIX®), Base Specifications, Issue 7 (IEEE Std 1003.1, 2013 Edition) behave as defined when called from or interrupted by a signal handler, with a single exception: when a signal interrupts an unsafe function and the signal handler calls an unsafe function, the behavior is undefined.

...

[C99 Rationale 2003]Subclause 5.2.3, "Signals and Interrupts"
Subclause 7.14.1.1, "The signal Function"
[Dowd 2006]Chapter 13, "Synchronization and State"
[IEEE Std 1003.1:2013] XSH, System Interfaces, longjmp
XSH, System Interfaces, raise
[ISO/IEC 9899:2011]Subclause 7.14.1.1, "The signal function"
[Open Group 2004] [OpenBSD]signal() Man Page
[Zalewski 2001]"Delivering Signals for Fun and Profit"

 

...