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:

  1. Explain why printf, malloc, and many libc helpers are unsafe in handlers
  2. Implement safe integer/string output using only async-signal-safe primitives
  3. 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 around write)
  • sio_puts(const char *s) (no strlen; do bounded scan)
  • sio_putl(long v) (integer formatting without sprintf)
  • 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 snprintf baseline (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