
* Eric Blake:
Does anyone know if glibc guarantees that opendir/readdir in between multi-threaded fork() and exec() is safe, even though POSIX does not guarantee that safety in general?
glibc supports malloc after multi-threaded fork as an extension (or as a bug, because it makes malloc not async-signal-safe). Lots of programs depend on this. OpenJDK even calls malloc after vfork, which is not officially supported (but of course we can't break OpenJDK).
I know that one approach to avoid having to close all fds is religiously using O_CLOEXEC everywhere (so that the race window of having an fd that would leak is not possible), but that's also an expensive audit, compared to just ensuring that things are closed after fork(). Are there any other ideas out there that we should be aware of (and no, pthread_atfork is not a sane idea)? (various BSD systems have the closefrom() syscall which is more efficient than lots of close() calls; and Linux may be adding something similar https://lwn.net/Articles/789023/), Is there any saner way to close all unneeded fds that were not properly marked O_CLOEXEC by an application linking against a multithreaded lib that must perform fork/exec?
I tried to add getdents64 (which got committed, but may yet move from <unistd.h> to <dirent.h>, to match musl) and <sys/direntries.h> (which did not) in glibc 2.30. Those interfaces are async-signal-safe (except on some MIPS variants, where getdents64 has complex emulation). If you do not want to use opendir/readdir, issuing getdents64 directly and parsing the buffer is your best option right now. (Lowering the RLIMIT_NOFILE limit does not enable probing for stray descriptors, unfortunately.) But opendir/readdir after fork should be fine, really.