Step 1 of 5 · Reading · ~4 min
Read
Processes & Scheduling
Signals & Process Control
A signal is the kernel's way to tap a process on the shoulder: Ctrl-C produces SIGINT, a bad memory access produces SIGSEGV, a closed pipe produces SIGPIPE, a child's exit produces SIGCHLD. It is software's version of an interrupt, and its handling has precise rules that programs rely on. In this lesson your program is the kernel's per-process signal state: a pending set, a blocked set, a disposition for each signal, and the delivery logic.
Numbers and bit masks
Classic Linux signals are numbered 1 to 31, and sets of signals are 32-bit masks where signal n is bit n - 1. SIGINT (2) is bit 1, mask 0x00000002; SIGTERM (15) is bit 14, mask 0x00004000. The signals in this lesson:
| No. | Name | Default action |
|---|---|---|
| 1 | SIGHUP | terminate |
| 2 | SIGINT | terminate |
| 3, 4, 6, 8, 11 | SIGQUIT, SIGILL, SIGABRT, SIGFPE, SIGSEGV | terminate and dump core |
| 9 | SIGKILL | terminate, cannot be caught, blocked or ignored |
| 10, 12 | SIGUSR1, SIGUSR2 | terminate |
| 13 | SIGPIPE | terminate |
| 14, 15 | SIGALRM, SIGTERM | terminate |
| 17 | SIGCHLD | ignore |
| 18 | SIGCONT | continue a stopped process |
| 19 | SIGSTOP | stop, cannot be caught, blocked or ignored |
| 20 | SIGTSTP | stop (Ctrl-Z) |
| 28 | SIGWINCH | ignore |
Disposition: what happens on delivery
Each signal has one of three dispositions: default (the action above), ignore, or handler (a function the process installed). SIGKILL and SIGSTOP always take their default action, so a stuck or runaway process can always be stopped. Trying to install a handler or ignore on them fails with EINVAL.
Pending and blocked
Sending a signal sets its bit in the target's pending mask. The kernel checks that mask when the process returns to user mode, delivers any signal that is pending and not blocked, and clears the bit. The process can block signals with a mask, for example while updating data a handler also touches; they stay pending until unblocked.
Two consequences matter:
- Standard signals do not queue. Pending is one bit. If
SIGINTarrives three times while blocked, it is delivered once. The merge is silent in real life; the exercise reports it. - Delivery order. When several signals become deliverable together, the lowest number is delivered first.
Another subtle rule: making a signal's disposition ignore discards a pending instance of it. And a signal that is blocked stays pending even if its disposition is ignore, because the disposition may change before it is unblocked.
How a handler actually runs
The kernel does not call the handler from inside the kernel. On the way back to user mode it saves the interrupted registers in a frame on the user stack, points the return address at the handler, and arranges for the handler's return to enter a tiny stub that calls sigreturn, which restores the frame. That is also why handlers should only call functions that are safe to run at any instant.
A worked trace
| Command | Output | Why |
|---|---|---|
BLOCK 2 | SIGINT blocked | |
SIGNAL 2 | SIGINT PENDING | held back |
SIGNAL 2 | SIGINT MERGED | same bit, not queued |
SIGNAL 15 | SIGTERM TERMINATE | not blocked, default action: the process dies |
Order on unblock: block 10 and 2, send SIGNAL 10 and then SIGNAL 2 (both held), install handlers for both and run SETMASK 0. The output is SIGINT HANDLED then SIGUSR1 HANDLED: signal 2 goes first although signal 10 was sent first.
Common mistakes
- Queueing a second instance of a blocked standard signal.
- Delivering pending signals in arrival order instead of lowest number first.
- Letting a process block, catch or ignore
SIGKILLorSIGSTOP. - Forgetting to clear the pending bit when delivering, or when
IGNOREis installed.
Your exercise
The starter holds the tables and parses commands. You write signal generation (pending, merge, immediate delivery) and the flush that delivers newly unblocked signals in order.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…