7 ms·
If you've ever read the Lions' Book commentary on 6th Edition Unix, you'll notice that many parts of the API as implemented back there are pretty solid -- quali
by pm215 10y ago
If you've ever read the Lions' Book commentary on 6th Edition Unix, you'll notice that many parts of the API as implemented back there are pretty solid -- quality, well designed interfaces that have stood the test of time.
Signals are not one of those parts. The 6th Ed signal handling code reads to me as somewhat of an afterthought whose use cases were mostly "kill the process for a fatal signal or terminal ^C", "ptrace for a debugger" and maybe SIGALRM. The data structures don't allow a process to have more than one pending signal -- if a new one comes along the fact an old one was pending is simply dropped. Running a signal handler automatically deregistered it, leaving a race condition if two signals arrived in close succession (this is a well known bug fixed by BSD later). And EINTR is an irrelevance if signals are generally fatal but its effects spread like poison through every other kernel API if you need your program to be reliable even with signals being delivered.
The worst bugs and races were fixed up by the BSD folks and others, but the underlying concept is an unfortunate combination of "basically irredeemable", "indispensable" (you have to have some kind of "kernel tells you something has happened" API, and signals are what we got) and "insidious" (thanks to EINTR). I think they're a strong candidate for "worst design decision in unix".
(PS: one of the reasons they stand out in 6th Ed is that so much of the rest of that code is so good!)
- silvestrov 10y agoI think signals are a "poor mans" implementation of threads and queues. They didn't have threads and queues back in the 70'ies, so they resorted to an ugly hack. Ditto with interruptable system calls. It's somewhat like the interrupt-level callbacks classic MacOS (version 1-9) had for network and file i/o. They too didn't have threads back then, so interrupt-callbacks was the only way to avoid blocking calls which would make the UI hang while waiting for network requests.
- pvg 10y agoI'm pretty sure they had threads and queues in the 70s. Or they wouldn't have bothered inventing primitives like semaphores in the 60s.
- deleted 10y ago[deleted]
- silvestrov 10y agoNo, threads is a rather late addition to unix. It came in the 90'ies. E.g. Sun Solaris got thread support in 1993. HP/UX got kerner threads in 1997.
- mturmon 10y agoThis is an interesting perspective. I think of signals the other way around -- that they came out of people realizing how useful hardware interrupts could be in allowing devices to talk to the kernel, so they engineered a similar affordance (signals) to allow the kernel to talk to processes. In the case of hardware interrupts (like for old keyboards), if you didn't grab that character off the hardware right away, it would vanish, or another one would take its place. As long as you were fast, it worked. Same with signals. As long as you don't try to do too much in the handler, it works. In other words, it was designed to be "good enough" if used properly (just like all hardware).
- adrianratnapala 10y ago...so interrupt-callbacks was the only way to avoid blocking calls I don't know how early MacOS works, but on Unix its not the _only_ way: that's what poll(), select() and the like are for. And while threads their uses, they don't really change this aspect. Eventually the thread must report a result, and the best way to do that is to report into to some queue that gets polled somewhere.
- cturner 10y ago"on Unix its not the _only_ way" Options were more limited in early unix. Use of signals as an adhoc IPC mechanism predates BSD sockets api (1983). Poll has something to do with SysV, so would have been later. There may have been other IPC mechanisms that were dropped before modern unix (but presumably dropped for good reasons). Art of Unix Programming refers to one called mx.
- Koromix 10y agoNeil Brown published an interesting series about Unix design mistakes a few years ago: https://lwn.net/Articles/414618/ https://lwn.net/Articles/414618/ The first part of the "Unfixable designs" article is about Unix signals.
- Qwertious 10y ago>The worst bugs and races were fixed up by the BSD folks and others, but the underlying concept is an unfortunate combination of "basically irredeemable", "indispensable" (you have to have some kind of "kernel tells you something has happened" API, and signals are what we got) and "insidious" (thanks to EINTR). I think they're a strong candidate for "worst design decision in unix". Suppose you were to throw the whole thing out and write a good replacement (and backwards-compatibility be damned), what would it be like?
- jbarham 10y agoFWIW Plan 9 uses what it calls a "notification" mechanism: http://plan9.bell-labs.com/magic/man2html/2/notify http://plan9.bell-labs.com/magic/man2html/2/notify
- adrianratnapala 10y agoWhile the "notification" system seems is cleaner than the signals system (and presumably avoids those races fixed by BSD) -- it does not seem fundamentally different. If I am understanding that man page correctly, it does nothing at all to fix EINTR: "If the note interrupted an incomplete system call, that call returns an error (with error string interrupted) after the process resumes."
- nitwit005 10y agoEINTR is only "needed" because of the situation where a call is made to a blocking system call like read, and a signal is received before it completes. It needs to cancel the blocking call so that it can run the signal handler. If you get rid of signals, you wouldn't need EINTR. Even with signals, what people do 99% of the time is just retry the system call immediately. It would probably have been much better to have it do so automatically by default, avoiding exposing EINTR to most users.
- JdeBP 10y ago... and, thence, SA_RESTART.
- pjmlp 10y agoNo time to read it back again, but if I remember correctly not even POSIX defines portable semantics for signals across implementations, it always leaves some room for implementation specific behavior.