Project 22: Signal-Safe Printf (Async-Signal-Safe Logging)
Project 22: Signal-Safe Printf (Async-Signal-Safe Logging)
Build a tiny
printf-like facility that is safe to call from a signal handler by using only async-signal-safe operations.
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Advanced |
| Time Estimate | Weekend |
| Language | C (Alternatives: Rust) |
| Prerequisites | Understanding of signals, reentrancy, and low-level I/O |
| Key Topics | Async-signal-safety, write(2), integer formatting, reentrancy |
| CS:APP Chapters | 8 (plus 12.7.1 for reentrancy/thread safety) |
1. Learning Objectives
By completing this project, you will:
- Explain why
printf,malloc, and many libc helpers are unsafe in handlers - Implement safe integer/string output using only async-signal-safe primitives
- Use your logger to harden signal paths in P11/P12/P17
2. Project Specification
Build a small library (e.g., sio.c/.h) that provides:
sio_write(const char *buf, size_t len)(thin wrapper aroundwrite)sio_puts(const char *s)(nostrlen; do bounded scan)sio_putl(long v)(integer formatting withoutsprintf)sio_printf(const char *fmt, ...)(optional, minimal specifiers:%s %d %x %p)
3. Testing Strategy
- Write a program that intentionally delivers signals at high frequency during heavy I/O and allocation.
- Prove โno deadlockโ: send SIGINT while another thread is logging.
- Validate formatting correctness against a normal
snprintfbaseline (outside handlers).
4. Common Pitfalls
- Calling non-safe functions inside your handler (including helpers that seem pure).
- Using global mutable state without protection (handlers can interrupt anywhere).
- Buffer overruns while formatting (keep buffers fixed-size).
5. Extensions
- Add a signal-safe ring buffer and a background โdrainโ thread (handler only enqueues).
- Add a crash reporter that prints registers from
ucontext_t(platform-specific).
6. Reference Reading
- CS:APP 3e โ Ch. 8 (Exceptional Control Flow), async-signal-safety discussion