Step 1 of 5 · Reading · ~3 min
Read
Production Concerns
Signals and the Terminal
After this lesson your shell handles Ctrl-C and Ctrl-Z the way a real one does: the keystroke reaches the command that is running in the foreground and not the shell, a background job is left alone, and a child never inherits a signal setting that would make it immune to Ctrl-C. You will model the rules that decide what a delivered signal does.
What a signal is
A signal is a small numbered message the kernel delivers to a process. Each process has, for every signal, a disposition that says what to do when one arrives:
- default: take the signal's default action. For most signals that is to terminate; SIGCHLD defaults to ignoring; SIGTSTP stops the process; SIGCONT resumes a stopped one.
- ignore: discard it.
- handler: run a function the program registered. The process is not killed.
Two signals cannot be changed at all: SIGKILL always terminates and SIGSTOP always stops. That is why they are the last resort.
| Signal | Number | Default action | Typed as |
|---|---|---|---|
| SIGHUP | 1 | terminate | |
| SIGINT | 2 | terminate | Ctrl-C |
| SIGQUIT | 3 | terminate | Ctrl-\ |
| SIGKILL | 9 | terminate, uncatchable | |
| SIGUSR1 | 10 | terminate | |
| SIGPIPE | 13 | terminate | |
| SIGTERM | 15 | terminate | |
| SIGCHLD | 17 | ignore | |
| SIGCONT | 18 | continue | |
| SIGSTOP | 19 | stop, uncatchable | |
| SIGTSTP | 20 | stop | Ctrl-Z |
A process killed by signal n reports status 128 + n, as the previous lesson showed.
Who receives Ctrl-C
The terminal does not know about your shell's jobs. When you press Ctrl-C it sends SIGINT to every process in the terminal's foreground process group. A process group is a set of processes with one group number. The shell gives each job its own group and then tells the terminal which group is in the foreground. Background jobs are in other groups and never see the keystroke.
Two inheritance rules
When a process forks, the child gets a copy of every disposition and the same process group. When a process calls exec, caught signals go back to the default (the handler code no longer exists) but ignored signals stay ignored. The second rule is the trap.
An interactive shell ignores SIGINT and SIGTSTP so that Ctrl-C does not kill the shell itself. If it forks and execs a program without changing that, the program inherits the ignore, and the user can no longer interrupt it. The correct sequence is: fork, then in the child put the dispositions back to default and move into the job's group, then exec.
Delivery rules for this lesson
For a live process, a signal produces one outcome:
- SIGKILL: terminated. SIGSTOP: stopped.
- SIGCONT: if the process is stopped it continues; otherwise it is caught if it has a handler and has no effect if not.
- Any other signal sent to a stopped process stays queued: report
pendingand change nothing. - Otherwise an ignored signal gives
ignored, a handled one givescaught, and the default action givesterminated,stoppedorignored.
Common mistakes
- Resetting handlers across exec but also resetting ignores, which hides the inheritance bug.
- Delivering Ctrl-C to every process instead of only the foreground group.
- Letting SIGKILL or SIGSTOP be ignored or caught.
- Forgetting that a stopped process cannot act on SIGTERM until it is continued.
Your exercise
The starter reads commands and runs the process table, the terminal and the dispatch. You implement the three rules in the middle: what fork copies, what exec resets, and what a delivered signal does. The most likely mistake is resetting ignored signals on exec.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…