5 ms·
I really hope when the time comes and someone reinvents the wheel and comes up with a new great OS, the new OS will NOT have signals. Those are one of the worst
by nemaar 10y ago
I really hope when the time comes and someone reinvents the wheel and comes up with a new great OS, the new OS will NOT have signals. Those are one of the worst things ever invented. The idea that your code is randomly interrupted and it starts to execute something else is just mind-blowingly bad. The real fun comes when you want to use different libraries with different signal handling ideas in the same process. It all goes to very quickly. The worst thing is that no one had the courage to say "okay guys, this is bad, let's just forget it ever existed and create a better alternative".
/rant
- smcl 10y agoI'm not an operating systems person, so I'm curious - what are the alternatives?
- Merad 10y agoWin32 uses messages for everything. While Windows does include signals[0], only three are actually used (SIGABRT, SIGFPE, SIGTERM), and in practice I don't think I've ever seen a Win32 program implement signal handlers. [0]: https://msdn.microsoft.com/en-us/library/xdkz3x12.aspx https://msdn.microsoft.com/en-us/library/xdkz3x12.aspx
- trungaczne 10y agoI don't think message queues and signals serve the same use case. Signal could be used for out-of-band communication.
- kevin_nisbet 10y agoYou may be right, but in practice the syscall is so limited that I think many programs basically process the syscall as a message anyways, that using a messaging model may make more sense, and be easier to work with. Someone correct me if I'm wrong, but because of the way the syscall callback operates, it could be interrupting threads at almost any stage. This makes executing the signal in a safe manner very difficult, and from the signal handler itself you can only run certain code. If i remember correctly, most signal handler implementations then get reduced to basically set some state and return, where the regular execution will then check for that state and react to it. Well, if your only going to process the signal during you main event loop anyways, then why not just exchange the information over a message queue, and send a message to the process when you want it to do something (ie reload configuration).
- trungaczne 10y agoWell, from what I know, sometimes you just have to have out of band communication, check the discussion in the comment here: http://250bpm.com/blog:70 http://250bpm.com/blog:70 It sounds like a necessary use case to me. While most people would probably not use it, that doesn't invalidate its existence. Most people would probably not touch any low level code either way.
- zvrba 10y agoActually, structured exception handling (SEH) is the closest equivalent of UNIX synchronous signals (SIGSEGV, etc., those that are caused by the program itself) on Win32. As for asynchronous signals, there's APC (asynchronous procedure calls). (See https://msdn.microsoft.com/en-us/library/windows/desktop/ms684954(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/ms6...) I find Win32 vastly superior than UNIX in this area.
- adrianratnapala 10y agoSignals are the user-space equivalent of a hardware interrupt. It's true that almost any computer that does anything useful in the real world needs to be notified about that world using interrupt service routines (ISRs). But that doesn't mean user programs need interrupts. OSes can and do use interrupts as a cues to notify processes via very different abstractions. Heres one way: User Process 99: read socket Foo. Kernel: socket Foo has no data yet, move 99 from the "running" list to the "sleeping" list. run process 86 User Process 86: do stuff << HARDWARE INTERRUPT!>> Kernel: Notice that 99 is waiting for this packet (via socket Foo). Copy network data into 99's read buffer. Move 99 back to the "running" list. Run some processes, soon enough 99 gets a turn. User process 99: Oh good! I have data. This sort of interface is usually much more useful for user applications than having the equivalent of their own ISR becuase it doesn't just send a notification -- it also controls the flow of the main application in a sane way. Simple, non-interactive applications can do this kind of blocking I/O all day long. More responsive applications need some kind of event loop. I.e. instead of blocking on an concrete I/O resource, they block notification service which tells them what I/O is available. In very different ways, Windows messages and Unix select()/poll() both do this. The end result is usually a callback driven program. This is slightly similar to signals/ISRs (since signals are a kind of callback) -- but the game-changing difference is that the callbacks are only called when the application has voluntarily gone back to the event loop.
- chubot 10y agoI'm not sure I understand this example. Signals allow the program to receive a notification whether they are blocked on I/O or running on the CPU (and receive it immediately in the latter case). The application can integrate signals with its event loop with the self-pipe trick, or it can use Linux-specific APIs to have signals delivered over a file descriptor. http://man7.org/linux/man-pages/man2/signalfd.2.html http://man7.org/linux/man-pages/man2/signalfd.2.html I'm not saying signals are fun, but I don't think you've proposed anything different/better.
- zAy0LfpBZLC8mAC 10y ago> Signals allow the program to receive a notification whether they are blocked on I/O or running on the CPU (and receive it immediately in the latter case). No, they don't. Just because signal handler code gets executed immediately, doesn't mean that the progam "receives" anything, as you cannot really touch anything that's also touched by the rest of the program, as you'd usually produce some form of race condition. The little that you can do safely usually is functionally equivalent to setting a flag for the rest of the program to process, which you can just as well achieve with any other "non-immediate" IPC mechanism, with much lower risk of getting it wrong. > The application can integrate signals with its event loop with the self-pipe trick, or it can use Linux-specific APIs to have signals delivered over a file descriptor. Which, for all itents and purposes, transforms them into yet another pipe/socket/event source, in wich case you might as well use one of the numerous other variants of those.
- theseoafs 10y agoMessage passing, mainly. I.e. if your program is an event-based loop, then an interrupt is just another kind of message that you can receive on your main thread.
- rwl4 10y agoSignals are almost the app version of interrupts which is a fundamental way the peripherals (and your programs!) communicate with the kernel. Sure handling them can be a pain in the ass, but I'd argue that signals are beautiful in their simplicity and extremely powerful. They are used for far more than signaling hang up and termination.
- cyphar 10y agoSignals are an incredibly brittle interface. Not only can you lose signals all the time (if a signal is sent to a process while it is handling another signal then you can lose that signal), but you lose a lot of semantic information because the model of signal is "random callback that you jump to and you lose your old stack state while in the signal" is incredibly lossy. There's a lot of other problems (signals not being queueable, as well as the fact that signals expose a bunch of kernel race conditions by design) but you get the gist. Unix did a lot of things right, but signals was certainly not one of them. Sometimes the simple ideas aren't the best ones.
- jcrites 10y ago> if a signal is sent to a process while it is handling another signal then you can lose that signal > signals not being queueable Are you sure? I'm not an expert on signal handling, but I believe these statements are not true in the case of signalfd(2), which allows you to read signals from a file descriptor and does not require a signal handler.
- zAy0LfpBZLC8mAC 10y agoIt is necessarily true because sending signals cannot block and queueing an unbounded number of signals would require unbounded amounts of memory.
- cyphar 10y agoSignal sending cannot block, so you'd need to have an unlimited amount of memory in order to guarantee that all signals are delivered. Not to mention that some signals allow you to block a process in the middle of a syscall (resulting in the lovely restart_syscall and EINTR hacks). Also, signalfd(2) has its own lovely host of problems (caused by the fact that a file descriptor and signals don't match in abstractions). On fork(), sendmsg() or exec() or any other interesting event, the file descriptor starts to lean towards breaking POSIX. In addition, because of signals' interactions with threads, you get some even odder interactions when you read from the fd in a multithreaded program (they share the file descriptor table but will read different data).