* Yann Ylavic: >> readdir is thread-safe. There used to be this idea that fdopendir >> could be implemented like this: >> >> DIR * >> fdopendir (int fd) >> { >> return (DIR *) fd; >> } >> >> And readdir would use a static buffer for the directory entry (like >> gethostbyname) instead of something which is allocated as part of the >> opaque the DIR * object (similar to a FILE *). Such systems may >> indeed have existed at one point, but I doubt that you can compile APR >> on them. It's unlikely that these systems will support readdir_r >> because it is much to recent an interface. > > Right, modern readdir()s seem to be thread-safe but with regard to > different directories only, at least Linux' man page states: > "In the current POSIX.1 specification (POSIX.1-2008), > readdir() is not required to be thread-safe. However, in modern > implementations (including the glibc implementation), concurrent calls > to readdir() that specify different directory streams are thread-safe. > In cases where multiple threads must read from the same directory > stream, using readdir() with external synchronization is still > preferable to the use of the deprecated readdir_r(3) function. It is > expected that a future version of POSIX.1 will require that readdir() > be thread-safe when concurrently employed on different directory > streams."
It's been a bit of a struggle to get this right. People are really concerned about the case where multiple threads read from the same directory stream. But how often does that happen in practice? >> For systems which use a buffer embedded in the DIR * object (and I'm >> not aware of any which don't), readdir is as thread-safe as memcpy, >> although some manual pages claim it is not. This is very likely an >> editorial mistake because thread safety guarantees for functions which >> operate on separate objects are still an evolving concept. > > Are you thinking of the above editorial? I meant this part: Preliminary: | MT-Unsafe race:dirstream | AS-Unsafe lock | AC-Unsafe lock | See POSIX Safety Concepts. <https://www.gnu.org/software/libc/manual/html_node/Reading_002fClosing-Directory.html> “MT-Unsafe race:dirstream” doesn't make much sense because we don't have this as a category for memcpy because for some reason, it is “obvious” for memcpy that it's only thread-safe if it is called for completely separate arguments. I think the Solaris manual also does not mark readdir as thread-safe, implicitly suggesting to use readdir_r in multi-threaded programs. But this suggestion isn't helpful on Solaris, either. >> Just stop using readdir_r. I know that many people are invested in >> that interface for various reasons, but sometimes, you just have to >> delete pointless code and get on with it. > > I'm not sure we can use readdir() blindy though, what if multiple > threads use it on the same dir? Then the current implementation is already broken because apr_dir_read does not perform any locking: The call to readdir_r can write to the d_name buffer, and the reads of the d_name in apr_dir_read constitute a data race. If you mean “the same directory on the file system”: What counts is the same DIR * object. If two objects iterate through the same directory, this does not matter because each DIR * object is required to keep its own iteration position.