About This Chapter
Chapter 21 continues the signal discussion from Chapter 20 and focuses entirely on signal handlers — how to write them correctly, how they can fail in subtle ways, and how to deal with system call interruption. These are essential topics for every Linux systems programmer and embedded engineer.
Each section below is a separate tutorial page with concept explanations, inline diagrams, working code examples, and interview questions.
All Sections
Two golden design patterns for signal handlers. Signals are not queued — what this means for your code. The self-pipe trick for event-loop programs.
What makes a function non-reentrant. The official POSIX list of async-signal-safe functions. Why malloc(), printf() and crypt() are dangerous inside handlers. Always saving errno.
The two problems with sharing variables between main and handler: compiler register caching and non-atomic access. Why you need volatile sig_atomic_t. Limits of ++ operator.
Why longjmp() breaks the signal mask on Linux. The POSIX fix: sigsetjmp() + siglongjmp(). The canJump guard variable pattern. Using abort() for abnormal termination with core dump.
How stack overflow + SIGSEGV creates a handler that can never run. Setting up an alternate stack so SIGSEGV can be caught. Three-step setup process. SIGSTKSZ, MINSIGSTKSZ, SS_ONSTACK.
Getting detailed signal info: who sent it, why, the fault address (for SIGSEGV), child exit details (for SIGCHLD). The three-argument handler. sa_sigaction vs sa_handler. All siginfo_t fields explained.
What happens when a signal interrupts read(), accept(), or select(). EINTR handling. SA_RESTART and which calls it covers. Which calls NEVER restart (poll, select, epoll). Implementing a read timeout using SIGALRM + EINTR.
Quick Reference: Key Functions
| Function / Concept | Header | Purpose | Section |
|---|---|---|---|
sigaction() |
<signal.h> |
Install signal handler with full control | 21.1 |
volatile sig_atomic_t |
<signal.h> |
Safe shared flag between handler and main | 21.1.3 |
sigsetjmp(env, 1) |
<setjmp.h> |
Save jump point + signal mask | 21.2.1 |
siglongjmp(env, val) |
<setjmp.h> |
Jump back from handler, restoring signal mask | 21.2.1 |
abort() |
<stdlib.h> |
Terminate with core dump via SIGABRT | 21.2.2 |
sigaltstack() |
<signal.h> |
Register alternate stack for signal handlers | 21.3 |
SA_ONSTACK |
<signal.h> |
Use alternate stack for this handler | 21.3 |
SA_SIGINFO |
<signal.h> |
Enable 3-argument handler with siginfo_t | 21.4 |
SA_RESTART |
<signal.h> |
Auto-restart interrupted blocking syscalls | 21.5 |
EINTR |
<errno.h> |
errno value when syscall interrupted by signal | 21.5 |
