3 ms·
Sigaction is pretty cool. Signals still suck though, if you need to stick to the POSIX specs. It's crazy that so many standard library functions will fail with
by nrclark 9y ago
Sigaction is pretty cool. Signals still suck though, if you need to stick to the POSIX specs.
It's crazy that so many standard library functions will fail with an EINTR errno if your program gets a signal while it's in a library function. Basically any library call that ever does any I/O of any kind (that means common stuff like open/dup/read/write, but also less obvious stuff like getpwuid).
Sigaction provides the SA_RESTART flag which _should_ auto-restart most calls, but it doesn't work everywhere. And the functions which do and don't auto-restart aren't documented anywhere that I've ever found.
As a result, any high-reliability program that installs signal-handlers basically needs to have a retry mechanism for every libc call that can result in an EINTR. Some functions might not need it, but I've never found a good way to tell which ones do and which ones don't. Select(), for example, doesn't support SA_RESTART. Neither does wait(). And that means they all need to be checked every time, if you're concerned with portability and reliability. And that's nuts.
IIf I could change one thing about sigaction in POSIX, it would be to add an SA_NOINTR flag to the sigaction API, which would let any POSIX library calls finish before presenting a signal.
That, plus I'd also add Linux's signalfd() to the POSIX standard so that we could do away with "this one weird trick from a DJB" that everybody uses now (and I'd make signalfd use the new SA_NOINTR).
- deleted 9y ago[deleted]
- iforgotpassword 9y agoAgreed. Years ago I wrote a daemon for Linux with glibc only, so I assumed I can just ignore EINTR everywhere, until I needed to use valgrind and suddenly had EINTRs everywhere. Rather than making signalfd POSIX, if we play make-a-wish let's just go for kqueue. Signalfd feels somewhat hackish, even though its simplicity admittedly has some appeal too.
- xenadu02 9y agoSignals are an example of false simplicity: they themselves are very simple at the cost of foisting the complexity on you and every library you use.
- cryptonector 9y ago+1 to kqueue. Burn epoll in a bonfire.
- cryptonector 9y agoIf you have a single-threaded program and you want to set a `do_exit` variable in your handler and hope the program notices it soon, you'll want your program not to be blocking in some system call for an I/O event that might never come. This is the reason that EINTR exists. It might have been better to have "restart-on-signal" / "interrupt-on-signal" be an argument to every system call that can block, but it's a bit late for that. So EINTR it is, and you just have to know -- it's all part of the cognitive load of dealing with POSIX/Unix/Linux/whatever. Win32 has its own things to know about (and plenty of them). The cognitive load is, I'll say, quite heavy, but you can always use a higher-level programming language whose run-time hides all of this for you.
- noselasd 9y agoThe system calls that are not restarted even when SA_RESTART is set, is documented here for linux: http://man7.org/linux/man-pages/man7/signal.7.html http://man7.org/linux/man-pages/man7/signal.7.html Look in the "Interruption of system calls and library functions by signal handlers" chapter after the "The following interfaces are never restarted after being interrupted" text.
- nrclark 9y agothat's actually pretty helpful! Do you know if there's an equivalent in the POSIX spec? I looked around for a while and didn't find one. I want my daemon to work on more than just Linux, so I'm trying hard to stick to pure POSIX.