Poison pills, a tale of interrupts versus highly structured systems
January 24, 2011
Once upon a time way back when, I was briefly involved with a research operating system that was written in a highly structured, layered, and modular manner with strong isolation between all of the components, in a strongly typed and scoped language (ie, all of the best practices of mid to late 1980s academic software engineering). It was also intended to be POSIX compatible, and this created a little problem.
Most of the time, Unix-like terminal handling is very nicely modular
and layered. You can easily design a stack of modules that process
terminal input from the raw hardware on up through terminal processing
and the eventual
Control-C is an extremely awkward thing in a highly modular and layered system. First, it's an asynchronous activity with immediate effect, and second its effects have (almost) nothing to do with terminal input. In a structured modular system, the terminal input handling code simply does not have direct access to the process handling code that sends signals; that access exists only at a much higher level in the overall kernel structure.
(Control-C is not the only input character with such non-local effects, but it is the one that you absolutely cannot get away with ignoring if you want to have an even vaguely usable system.)
To get around this, the system implemented control-C handling with a special hack that I heard called 'poison pills'. Normally the terminal system's 'read' interface returned characters, but it could also return special magic results to signal various special events, ie poison pills (so called presumably because they generally killed the process involved in consuming them). These poison pills propagated up through the various levels of code, and once a poison pill made it up to the high level that had access to the process interface, it was 'eaten' and the process signaled or killed outright.
(Much of this was carefully wrapped up in various opaque types and module interfaces.)
While I sort of admired the poison pill hack, the major lesson that I took away from this experience was that excessively strict modularity and isolation was a bad thing. Real systems do not nicely break down into neat hierarchies of functions and modules because there are connections that cut across your clean boundaries. While you can handle these 'correctly' inside your design with enough work, the contortions required to do this are generally worse than those required to deal with the cross connections.
(The other lesson I took away was that operating systems should not be written in highly structured and controlled languages.)
* * *
Atom feeds are available; see the bottom of most pages.