4 ms·
Question from someone not knowing much about low-level programming and dealing with signals: If signals are so problematic, why rely on them? Is the functional
by treve 11y ago
Question from someone not knowing much about low-level programming and dealing with signals:
If signals are so problematic, why rely on them? Is the functionality useful for other things other than dealing with 'emergencies'?
One thing I can see that is useful, is that it allows a program to gracefully deal with a kill, but many applications seem to have a 'graceful stop' mechanism that doesn't need signals.
- geofft 11y agoA lot of functionality is only available via signals. For instance, there's no way other than SIGCHLD to be asynchronously notified when a process exits (unless you want to dedicate a thread to running wait()). There's no way other than SIGWINCH to be notified when your terminal gets resized. You could certainly imagine some kernel extensions that take all of this useful functionality and make it available in ways other than signals, leaving just signals for things you have to deal with immediately like SIGSEGV (so you can print a nice error message before quitting), but they don't exist yet. I imagine some of the intent behind signalfd was to do this all at once for all signals, but it didn't quite work.
- osandov 11y ago> You could certainly imagine some kernel extensions that take all of this useful functionality and make it available in ways other than signals, leaving just signals for things you have to deal with immediately like SIGSEGV (so you can print a nice error message before quitting), but they don't exist yet. In the SIGCHLD case, there's a proposed CLONE_FD flag to clone which would return a file descriptor instead of a PID. This fd could be read poll'd on and read from, which is much nicer than dealing with SIGCHLD. See http://lwn.net/Articles/638613/ http://lwn.net/Articles/638613/ So those kernel extensions are happening :)
- quotemstr 11y agoclonefd is a very limited solution. What we really need is the ability to open a file descriptor handle to any process. That ability solves all sorts of race conditions. Conveniently, we already have an interface to open file descriptors for processes: /proc. We just need to extend its semantics slightly.
- colin_mccabe 11y agoMaybe I'm misunderstanding, but wouldn't opening a file descriptor to a process via /proc have the same race condition issues with process id wraparound? After all, processes in /proc are opened by process ID (the only exception I can think of is /proc/self... maybe I missed some other exceptions?) Overall, it seems easier to avoid process ID wraparound attacks via using the full 32-bit number space for PIDs. There may be a few programs that need to be changed because they did something silly like cast pid_t to short, but I think overall most programs would work just fine. As far as I can remember, the reason for using low numbers was because people didn't want to type longer ones at the shell. Internally the kernel and libraries store everything as 32-bit, at least on Linux.
- quotemstr 11y ago> Maybe I'm misunderstanding, but wouldn't opening a file descriptor to a process via /proc have the same race condition issues with process id wraparound? Absolutely. But once you've opened the file descriptor, the kernel would guarantee that its corresponding process ID would remain unused until you closed the file descriptor. (For example, it could keep the process a zombie if it exits.) This way, it's possible to write a reliable killall: walk /proc, call openpid() on each entry, and with the PID FD open, examine the process's user, command line, or whatever else, kill the process if necessary, and close the process file descriptor. No race.
- colin_mccabe 11y agoBut once you've opened the file descriptor, the kernel would guarantee that its corresponding process ID would remain unused until you closed the file descriptor. (For example, it could keep the process a zombie if it exits.) That seems like it would open you up to a trivial denial-of-service attack where some attacker just spawns a bunch of processes and never closes the /proc handles. Then you can't start any more processes because there are no more process IDs available. The only workaround is to have a larger PID space, which poses the question... why not just have a larger PID space in the first place and skip the new, non-portable API?
- scott_s 11y agoI think geofft's answer is a good one, but I wanted to add a different point: you can't not deal with signals. They're going to happen, and even if you block or ignore them, that doesn't change the fact that something happened that may be important to your process. That's just the rules of the game.
- crdoconnor 11y ago>One thing I can see that is useful, is that it allows a program to gracefully deal with a kill, but many applications seem to have a 'graceful stop' mechanism that doesn't need signals. I don't see how that's possible. You need to listen to at least SIGTERM, SIGINT and SIGHUP if you're going to gracefully stop.