class: center, middle # Signals ## Alan Cox --- layout: true --- # What Are Signals? - Software interrupts for asynchronous event notification - Sent by the kernel or other processes - Common signals: - `SIGINT` - Interrupt from keyboard (Ctrl+C) - `SIGALRM` - Timer expired - `SIGUSR1`, `SIGUSR2` - User-defined signals - `SIGKILL`, `SIGTERM` - Termination requests --- # Signal Handlers - Functions that run when a signal is delivered - Installed with `sigaction(2)` - Signals can interrupt system calls, causing them to fail with `EINTR`; use `SA_RESTART` to avoid this --- # The Problem: Race Conditions .twocolumn[ .col[ ``` volatile int counter = 0; void handler(int sig) { if (counter % 2 == 0) { // Error: counter is even! } } int main(void) { // Install handler, set timer... while (...) { counter++; // Signal can arrive here! counter++; } } ``` ] .col[ - Signal can arrive at any time - Handler may see inconsistent state - Need to control when signals are delivered ] ] --- # Signal Masking with `sigprocmask(2)` ``` int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); ``` - Block signals to defer their delivery - `how` values: - `SIG_BLOCK` - Add signals to blocked set - `SIG_UNBLOCK` - Remove signals from blocked set - `SIG_SETMASK` - Replace blocked set entirely - Blocked signals are held pending, not lost --- # Waiting for Signals with `sigsuspend(2)` ``` int sigsuspend(const sigset_t *mask); ``` - Atomically unblocks signals and suspends until one arrives - Replaces signal mask with `mask` temporarily - Returns after a signal handler executes (returns -1, `errno` = `EINTR`) --- # Blocking Signals During Handlers - `sa_mask` specifies signals to block while handler runs - Prevents one handler from interrupting another - Signal being handled is automatically blocked --- # Sending Signals with `fork(2)` and `kill(2)` - `fork(2)` creates a child process - Returns 0 in child - Returns child's PID in parent - `kill(2)` sends a signal - `kill(pid, sig)` - `getppid()` returns parent's PID --- # Discussion Questions - Why can `write()`'s return value be ignored in the signal handler? - Why must `sigprocmask` be called before `setitimer`? --- class: center, middle # Get Started!