How do I close() a file in a multithreaded program?

Unfortunately, the answer to this question is complicated.

It starts easy enough; the HP-UX manual says:

[EINTR] An attempt to close a slow device or connection or file with
pending aio requests was interrupted by a signal. The file descriptor
still points to an open device or connection or file.

and SunOS/Solaris appears to have the same behavior, so simply retry if we get EINTR, right?

But FreeBSD always destroys the file descriptor before it returns EINTR, so we need the opposite algorithm there; retrying will destroy other (recently created by other threads) file descriptors.

It gets worse though: A quick check of the Linux kernel source code shows that Linux destroys the file descriptor before it returns EINTR like FreeBSD, but prior to 2.6.24 on NFS-mounted filesystems - we don't.

It gets much worse: OSX normally works like FreeBSD, but setting $COMMAND_MODE can load a wrapper in -lSystem where the library function close() will call pthread_testcancel() which can return EINTR before the close() system call has fired off.

Now if you only ever create (open/accept/etc) and destroy (close) file descriptors in a single thread, you can ignore this problem: You're effectively single-threaded as far as this problem is concerned, but if you don't, closing files is complicated, and that's where this library comes in:

  1. Include close.c in your project and close.h in every file.
  2. Wrap any routine that creates file descriptors with safeclose_lock() and safeclose_unlock()
  3. Call safeclose() instead of close()

I'd like to know about anyone actually using safeclose, since you will undoubtedly have other architecture-related problems that may be worth discussing: