Project 8: Signal Handler
Proper signal handling for an interactive shell: Ctrl+C (SIGINT) interrupts the foreground job but not the shell, Ctrl+Z (SIGTSTP) suspends the foreground job, and SIGCHLD lets you track child termination/stopping.
Quick Reference
| Attribute | Value |
|---|---|
| Primary Language | C |
| Alternative Languages | Rust, Zig |
| Difficulty | Level 3: Advanced (The Engineer) |
| Time Estimate | 1 week |
| Knowledge Area | Operating Systems / Signals |
| Tooling | Unix Shell |
| Prerequisites | Projects 1-5, understanding of signals |
What You Will Build
Proper signal handling for an interactive shell: Ctrl+C (SIGINT) interrupts the foreground job but not the shell, Ctrl+Z (SIGTSTP) suspends the foreground job, and SIGCHLD lets you track child termination/stopping.
Why It Matters
This project builds core skills that appear repeatedly in real-world systems and tooling.
Core Challenges
- Ignoring signals in shell, not in children (sigaction before/after fork) → maps to signal inheritance
- SIGCHLD handling (reaping zombies, detecting stopped jobs) → maps to async notification
- Signal-safe functions (can’t call printf in signal handler) → maps to reentrancy
- Interrupting system calls (EINTR handling) → maps to robust programming
- Terminal signals and process groups (only foreground group gets SIGINT) → maps to job control foundation
Key Concepts
- Signal handling: “The Linux Programming Interface” Chapters 20-22 - Kerrisk
- Async-signal-safe functions: “Advanced Programming in the UNIX Environment” Chapter 10.6 - Stevens
- Process groups and signals: “The GNU C Library Manual” Chapter 28 - GNU
Real-World Outcome
$ ./mysh
mysh> sleep 100
^C # Ctrl+C interrupts sleep
mysh> # But shell survives and prompts again
mysh> sleep 100
^Z # Ctrl+Z suspends sleep
[1]+ Stopped sleep 100
mysh> sleep 200 &
[2] 12346
mysh> # Shell doesn't block
[2] Done sleep 200 # Background job completion reported
mysh>
Implementation Guide
- Reproduce the simplest happy-path scenario.
- Build the smallest working version of the core feature.
- Add input validation and error handling.
- Add instrumentation/logging to confirm behavior.
- Refactor into clean modules with tests.
Milestones
- Milestone 1: Minimal working program that runs end-to-end.
- Milestone 2: Correct outputs for typical inputs.
- Milestone 3: Robust handling of edge cases.
- Milestone 4: Clean structure and documented usage.
Validation Checklist
- Output matches the real-world outcome example
- Handles invalid inputs safely
- Provides clear errors and exit codes
- Repeatable results across runs
References
- Main guide:
SHELL_INTERNALS_DEEP_DIVE_PROJECTS.md - “The Linux Programming Interface” by Michael Kerrisk