13 ms·
I wonder if EINTR can also happen on macOS? macOS is certified UNIX, and the post talks about Unix in general, that's why I wonder. I've inspected the family o
by self_awareness 6y ago
I wonder if EINTR can also happen on macOS? macOS is certified UNIX, and the post talks about Unix in general, that's why I wonder.
I've inspected the family of fopen() functions (fread, fwrite), and they don't handle EINTR. Do they delegate this task to the caller? Or that EINTR doesn't exist there? I mean, the error code itself is used, and by quickly skimming XNU sources I can see it's used in some NFS code, but can it happen when reading from or writing to local storage (hard disk)?
Edit: some minutes later, I can see that e.g. libstdcxx supports EINTR, so maybe it can happen on macOS as well (the xwrite() function):
https://opensource.apple.com/source/libstdcxx/libstdcxx-104.1/src/basic_file.cc.auto.html https://opensource.apple.com/source/libstdcxx/libstdcxx-104....
- comex 6y agoI just tested it on macOS and Linux with the two main sources of EINTR: signal handlers and attaching a debugger. I tested by interrupting a read from stdin, but the behavior for disk reads and writes should be similar. Signal handlers: POSIX specifies that, after a process runs a signal handler which was triggered when it was in the middle of a system call, either the system call will automatically be resumed or it will fail with EINTR, depending on a per-signal-handler setting. If the signal handler was set with sigaction(), this setting is the SA_RESTART flag; otherwise it can be set by siginterrupt(), but the default seems to be implementation-defined(?). Anyway, it seems that both macOS and Linux enable restarting by default. (But well-written library code should take into account the possibility that something else in the process could have decided to disable it.) Attaching a debugger (using ptrace): This interrupts system calls because the debugger expects to see a userland state. On Linux it seems to automatically restart the system call, but on macOS it produces EINTR. This behavior doesn't seem to be configurable on either OS. On both OSes, when EINTR does occur in read(), fread() does not cover up for it by automatically retrying, regardless of whether it successfully read any bytes beforehand.
- saagarjha 6y agoWhich libc were you using on Linux, or were you making raw system calls? Because I think glibc’s behavior is to EINTR unless you define _GNU_SOURCE, which seems to me to be incompatible with your description…
- comex 6y agoglibc, Debian package version 2.31-3, without any special defines. Here is the program I used: https://gist.github.com/comex/58ba394588478bb1d506a998850b9436 https://gist.github.com/comex/58ba394588478bb1d506a998850b94... If I run the program and press Ctrl-C, it prints "interrupted" but then keeps going. However, if I add `siginterrupt(SIGINT, 1)` after the call to signal(), interrupting the read() produces EINTR as expected. Interestingly, the glibc manual used to state that the default behavior depended on the presence of _BSD_SOURCE or _GNU_SOURCE, but in 2014 it was changed to state that the default is always to use EINTR: https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=manual/signal.texi;h=51f68b5d3ec59ea8a662c18360a3ba15cebe80ef;hp=f0e57ddbe41af3b0948d64c1dea420c6b1db9928;hb=c941736c92fa3a319221f65f6755659b2a5e0a20;hpb=e8d8d7ec98af7c3777fd664adca8be5630afbc90 https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=manual/...
- saagarjha 6y agoOh, huh, that’s really interesting! I didn’t realize that glibc had changed their behavior; I wonder if this broke any applications…