3

This page describes the guaranteed behavior of the functions readdir and readdir_r and contains the following sentence:

After a call to fork(), either the parent or child (but not both) may continue processing the directory stream using readdir(), rewinddir() or seekdir(). If both the parent and child processes use these functions, the result is undefined.

I'm writing a fork-safe wrapper around the DIR*-related family of functions as an exercise and I'm wondering whether it's safe to closedir the directory stream in both the parent and the child simultaneously or whether the process that doesn't continue reading from the directory stream isn't supposed to interact with the directory stream at all.

Greg Nisbet
  • 3,076
  • 1
    Executing in other process needs ptrace. Or you have setup IPC between parent and child so they can communicate and do the requested action. – 炸鱼薯条德里克 Mar 22 '19 at 01:49
  • @炸鱼薯条德里克 I was going to have a static atomic flag and register a fork handler and force the user to pick when opendiring the directory whether the parent or child inherits it on fork. My wrapper library that doesn't exist yet will promise nothing if you use the unwrapped library calls in addition to the wrapper. – Greg Nisbet Mar 22 '19 at 02:00
  • Don't know what you're talking about. If you want disallow some process from accessing some file, then use mount namespace or simply revoke the file permissions for that user or use selinux or whatever. Then that process can only get an fd from another privileged process – 炸鱼薯条德里克 Mar 22 '19 at 02:03
  • @炸鱼薯条德里克 I see. I'm not trying to force processes that I have no control over to "play by the POSIX rules" or prevent them for accessing particular files. I'm trying to understand what exactly the POSIX rules are regarding directory streams. My motivation for understanding what the rules are is to write a wrapper library around the POSIX API that makes it easier to write programs that only use the API in defined ways. – Greg Nisbet Mar 22 '19 at 02:13
  • @炸鱼薯条德里克 there’s no IPC or ptrace here, the fds are shared because opendir was called before fork. The relevant scenario is fork without exec, so the execution context is identical in the parent and child. – Stephen Kitt Mar 22 '19 at 06:10
  • @Stephen But how can you close fd in the child from parent? I think They wouldn't be sharing one file descriptor table if you use glibc fork(). Child just get a copy – 炸鱼薯条德里克 Mar 22 '19 at 08:50
  • @Stephen That doesn't seems to be the behavior described in the man page, which say fork is implemented without CLONE_FILES, then child gets a copy of file descriptor table. – 炸鱼薯条德里克 Mar 22 '19 at 09:55
  • @炸鱼薯条德里克 sorry, you’re right, my test was flawed; the child gets a copy of the file descriptors, and the kernel only releases the underlying file description when the last file descriptor is closed. – Stephen Kitt Mar 22 '19 at 10:14
  • Maybe there's something you can register to pthread_atfork to close those DIR in the child. – 炸鱼薯条德里克 Mar 22 '19 at 10:29

1 Answers1

2

As a general comment, I recommend referring to the current description of readdir (it doesn’t change anything here).

closedir does two things in practice: it frees the memory allocated by the C library to keep track of the directory stream, and if the opendir/readdir/closedir family of functions are implemented using file descriptors, it closes the file descriptor. Both of these operations apply to the process calling them, not a potential parent or child from a fork: freeing the directory stream only affects the calling process’ memory (if necessary, creating a copy of the relevant pages to make changes to them independently of any other process with a shared memory map from a copy-on-write fork), and closing the file descriptor only affects the current process (if another process has a file descriptor sharing the underlying file description, the file description isn’t released).

Thus, while readdir isn’t safe to call from different processes on a shared directory stream (because of the underlying shared file description), closedir is safe.

Stephen Kitt
  • 434,908