Linux System Programming · intermediate · ~12 min

Writing safe signal handlers — async-signal-safe rules

Know which functions you can call from a signal handler — and why printf isn't on the list.

Lesson

A signal handler interrupts your code at an arbitrary point — possibly in the middle of malloc(), printf(), or pthread_mutex_lock(). If you then call those same functions from the handler, you can deadlock (the mutex is already held by the interrupted thread) or corrupt internal state.

The Linux man page signal-safety(7) lists the async-signal-safe functions — the ones you may legally call. The headline set: write, read, _exit, kill, signal, sigaction, sigprocmask, plus most simple syscalls. Notably not safe: printf, malloc, free, anything using stdio buffers, anything that grabs a libc lock.

The defensive pattern is: the handler sets a flag; the main loop does the work. Use a volatile sig_atomic_t for the flag — it's the only type the C standard guarantees atomic against signal delivery.

Code examples

#include <signal.h>
#include <unistd.h>
#include <string.h>

static volatile sig_atomic_t want_quit = 0;

static void on_term(int sig) {
    (void)sig;
    want_quit = 1;
    /* write() IS async-signal-safe; printf() is not. */
    const char msg[] = "got SIGTERM, will exit soon\n";
    write(STDERR_FILENO, msg, sizeof msg - 1);
}

int main(void) {
    struct sigaction sa = {0};
    sa.sa_handler = on_term;
    sigemptyset(&sa.sa_mask);
    sigaction(SIGTERM, &sa, NULL);

    while (!want_quit) { sleep(1); }
    /* All the real cleanup happens out here. */
    return 0;
}

Common mistakes

  • Calling printf, fprintf, puts, sprintf from a handler. They're not async-signal-safe.
  • Calling malloc/free or anything that allocates (which includes most logging libraries).
  • Reading a non-atomic global. Use volatile sig_atomic_t for flags.

Summary

Handlers must only call async-signal-safe functions (write, _exit, kill, sigaction, …). Pattern: set a volatile sig_atomic_t flag in the handler, react in the main loop.

Practice with these exercises