Wow, close sucks so hard on Unix, due to EINTR and platform specific (and not well documented) behavior.
https://news.ycombinator.com/item?id=3363819
http://austingroupbugs.net/view.php?id=529
Linux’s position is very awkwardly stated in the man page:
Note that the return value should only be used for
diagnostics. In particular close() should not be retried after an
EINTR since this may cause a reused descriptor from another thread to
be closed.
That actually means “Even on EINTR, the file descriptor is closed”. On Linux at least. HP-UX is NOT the same.
One workaround is to block SIGINT temporarily when doing the close(). That sucks for performance and CTRL-C purposes, so IMHO that should only be done if you have no clue what the platform you are on does with EINTR.
AIX appears to have the linux behavior. Not sure about BSD/Mac.
There’s also the question of how EINTR works in the IO libs. Python will raise a KeyboardInterrupt if close returned EINTR. https://hg.python.org/cpython/file/2db41d551a4f/Modules/_io/fileio.c#l74 - PyErr_SetFromErrno does it.
The exemption of 0,1,2 fds from being closed (let alone checking err from there close) also greatly concerns me: https://github.com/rust-lang/rust/blob/master/src/libstd/sys/unix/fs.rs#L136-L151 Is main() { println!(“hello world”); } actually not safe due to missing checks on close()?