Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> implementations of stdio in libc generally do the right thing

Tell me, what is the "right thing" for stdio to do when it sees EINTR? It strikes me that this can't really be solved at the library level. There are times when you'll want to retry and there are times when you'll want to drop your work and surface the error to the caller. Doesn't seem to me like a library can decide which is which. Which is probably why the I/O syscalls need to surface it in the first place. (I'd argue if a library like stdio, which does nothing but wrap syscalls and buffer stuff, can decide it, then there's no need for EINTR to exist at all because the syscall could theoretically make the same decisions.)



The right thing is almost always to retry the syscall. Syscalls on Unix return EINTR because it makes the kernel simpler, which was a key design goal in Unix[1]. If you need to do something when a signal fires, you do it in a signal handler (relying on EINTR instead of a signal handler is error-prone because if the signal fires between syscalls you lose it).

That's the theory anyways - in practice it's really hard to use signal handlers to do stuff because of things like threads and async-signal safety. There are newer syscalls like pselect() which let you atomically unblock signals, execute the syscall, and re-block the signals, meaning EINTR can be used reliably, and then there's the even newer Linux-only signalfd() syscall which lets you receive signals via a file descriptor. But stdio is still very much oriented for the older signal handler approach.

[1] See the paper "The Rise of ``Worse is Better''" http://www.stanford.edu/class/cs240/readings/worse-is-better...


Yes, I'm aware, "almost always". Not always, though. I was thinking specifically of an application that might want to use signals to cancel blocking I/O and continue running.

(PS: When I wrote my reply I was also already familiar with your linked article, the challenges of signal safety, and the signalfd() syscall. Surely an interesting set of topics but I still maintain that a library doesn't really have a "good" way to deal with EINTR, especially if all it does is wrap read or write.)


Simplest solution would be for libc to export some flag that could be set in signal handler signifying that I/O operation should be aborted.

as for the simpler kernel, I think that windows NT/VMS solution where user code has to explicitly block on I/O completion is simpler kernel-wise, but leads to unnecessary complexity in applications (which is abstracted away by winapi, but it's sometimes leaky abstraction). On the other hand, most common application for interrupting syscalls is timeouts and then killing the thread is most often what you want.

In all, EINTR is not way to find out that there was an signal during syscall but an hack to get process to meaningful state the easiest possible way when signal handler runs. By the way for some syscalls post-2.6 linux does something reasonably similar to ITS' pclusering transparently without returning EINTR.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: