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 read() system call returning; the driver returns raw characters, the processing layer handles basic line editing and accumulates the result into lines, and so on. Then some joker hits control-C.

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.)

Written on 24 January 2011.
« The question of how long our greylisting interval should be
The modern Python web application stack (as I understand it) »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Mon Jan 24 01:10:09 2011
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.