UNIX Signals
What signals are
A signal is an asynchronous notification sent to a process, indicating that a particular event has occurred. Signals are the simplest UNIX IPC mechanism: they carry almost no data — just the signal number (an integer) — and the fact of their delivery.
Standard signals
| Signal | Number | Default action | Meaning |
|---|---|---|---|
SIGINT | 2 | Terminate | Interrupt from keyboard (Ctrl+C) |
SIGKILL | 9 | Terminate | Force-kill (cannot be caught or ignored) |
SIGSEGV | 11 | Core dump + terminate | Invalid memory reference |
SIGCHLD | 17 | Ignore | Child process terminated or stopped |
SIGALRM | 14 | Terminate | Timer expired (from alarm()) |
SIGPIPE | 13 | Terminate | Write to a pipe with no readers |
SIGUSR1 | 10 | Terminate | User-defined signal 1 |
SIGUSR2 | 12 | Terminate | User-defined signal 2 |
SIGTERM | 15 | Terminate | Polite termination request |
SIGSTOP | 19 | Stop | Suspend process (cannot be caught or ignored) |
Signal disposition
A process can respond to a signal in three ways:
- Default action: the kernel-defined response (terminate, core dump, stop, ignore).
- Catch: register a signal handler with
signal()orsigaction(). When the signal is delivered, the handler runs (in user mode, on the process’s stack). After the handler returns, the process resumes where it was interrupted (roughly — signals interrupt system calls, which may returnEINTR). - Ignore: tell the kernel to discard the signal.
SIGKILLandSIGSTOPcannot be ignored.
Signal delivery vs generation
A signal is generated when the event occurs (e.g., timer expires, child exits, user presses Ctrl+C). It is pending until the kernel delivers it. Delivery happens when:
- The target process is scheduled to run.
- The target process is returning from kernel mode to user mode (e.g., after a system call or interrupt handler).
The kernel never delivers a signal to a process running in user mode by interrupting the instruction stream — delivery is deferred to the kernel→user transition.
Unreliability of signals
Signals are not a reliable IPC mechanism for passing data:
- Multiple instances of the same signal may be merged: if a process has one
SIGCHLDpending and another child terminates, only oneSIGCHLDis delivered, not two. The process cannot tell from the signal alone that two children died. - Signals carry no payload beyond the number.
sigqueue()withSA_SIGINFOcan attach a small integer, but this is POSIX real-time extensions and not part of the core IA syllabus. - Signals interrupt system calls. A
read()that is blocked waiting for data may return-1witherrno == EINTRif a signal is delivered, forcing the programmer to restart the call.
Blocking signals
A process can block (mask) signals via sigprocmask(). Blocked signals remain pending until unblocked, at which point they are delivered. This is used to create critical sections where certain signals must not interrupt a sequence of operations.
Signal masks are inherited across fork() and preserved across exec().
Summary
- Signals are lightweight, asynchronous event notifications carrying a signal number.
- A process can catch, ignore, or accept the default action for a signal.
- Signals are unreliable for data transfer — they can be merged and carry minimal payload.
- Delivery is deferred to kernel→user transitions; blocked signals remain pending.
SIGKILLandSIGSTOPare the only truly unstoppable signals.