Skip to content
Lesson 15 of 24

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.NameDefault action
1SIGHUPterminate
2SIGINTterminate
3, 4, 6, 8, 11SIGQUIT, SIGILL, SIGABRT, SIGFPE, SIGSEGVterminate and dump core
9SIGKILLterminate, cannot be caught, blocked or ignored
10, 12SIGUSR1, SIGUSR2terminate
13SIGPIPEterminate
14, 15SIGALRM, SIGTERMterminate
17SIGCHLDignore
18SIGCONTcontinue a stopped process
19SIGSTOPstop, cannot be caught, blocked or ignored
20SIGTSTPstop (Ctrl-Z)
28SIGWINCHignore

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:

  1. Standard signals do not queue. Pending is one bit. If SIGINT arrives three times while blocked, it is delivered once. The merge is silent in real life; the exercise reports it.
  2. 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

CommandOutputWhy
BLOCK 2SIGINT blocked
SIGNAL 2SIGINT PENDINGheld back
SIGNAL 2SIGINT MERGEDsame bit, not queued
SIGNAL 15SIGTERM TERMINATEnot 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 SIGKILL or SIGSTOP.
  • Forgetting to clear the pending bit when delivering, or when IGNORE is 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.

Up nextUser Mode & Privilege RingsSystem Calls & I/O

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…