How to know if a Linux system call is restartable or not?

close is a rather special case. Not only is it not restartable on Linux; when close returns with EINTR on Linux, it has actually already succeeded, and making another call to close will fail with EBADF in single-threaded processes and cause extremely dangerous file-descriptor races in multi-threaded processes.

As of the published POSIX 2008, this behavior is permitted:

If close() is interrupted by a signal that is to be caught, it shall return -1 with errno set to [EINTR] and the state of fildes is unspecified.

This issue was raised with the Austin Group (as Issue #529) and it was resolved to revise the specification such that returning with EINTR means the file descriptor is still open; this is contrary to the current Linux behavior. If the file descriptor has already been closed at the time the signal is handled, the close function is now required to return with EINPROGRESS instead of EINTR. This can be fixed in userspace on Linux, and there is an open glibc bug report, #14627 for it, but as of this writing it has not received any response.

This issue also has serious implications for POSIX thread cancellation, the side effects of which are specified in terms of the side effects upon returning with EINTR. There is a related issue on the Austin Group tracker, Issue #614.

Leave a Comment