Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

os: ReadDir and Readdir on a File opened from a relative path try the wrong paths for FileInfo structs #62028

Open
bcmills opened this issue Aug 14, 2023 · 2 comments
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@bcmills
Copy link
Contributor

bcmills commented Aug 14, 2023

What version of Go are you using (go version)?

$ go version
devel go1.22-98bacdeafe Mon Aug 14 12:51:16 2023 +0000

Does this issue reproduce with the latest release?

Yes.

What did you do?

  1. Use os.Open to open an os.File for a relative directory.
  2. Call os.Chdir to change the current working directory.
  3. Call ReadDir or Readdir on the File opened in step (1).
  4. Inspect the resulting FileInfos.

(https://go.dev/play/p/bLLMvUJGu_u?v=gotip)

What did you expect to see?

The FileInfos should correspond to the directory entries relative to the File.

What did you see instead?

On Linux:

It isn't clear to me how this can be fixed in general — it is possible to use fdopendir to read the correct entries while the parent file is still open, but if the parent file is closed before the Info method is called on the returned DirEntry, I don't see a standard API to reliably open the correct path.

@bcmills bcmills added this to the Backlog milestone Aug 14, 2023
@bcmills bcmills added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Aug 14, 2023
@rsc
Copy link
Contributor

rsc commented Aug 14, 2023

In general Chdir breaks plenty of invariants, and we're not likely to try to work around that fact, simply because it's impossible to catch them all and just makes things more brittle. The only safe Chdirs are (1) at quiet moments when nothing else is going on and you're not going to try to reuse FS state from before the Chdir afterward, which typically reduces to (1a) at startup, and (2) during os/exec by setting cmd.Dir, which doesn't affect your process.

If there was some compelling use case where Open(dir), Chdir, ReadDir+Info, dir.Close was common, then I think the fix would be optimistic fstatat in the implementation of Readdir and the implementation of DirEntry.Info, with the latter falling back to name-based stat if the directory fd has been closed. But I'd want to see that use case before complicating this code. A racing Chdir in another goroutine would be the most common way to get that sequence, but in that case the Chdir is racing with Open and so you have bigger problems.

Leaving this open but probably we won't fix this unless there is a more compelling demonstration of this arising in actual practice.

@bcmills
Copy link
Contributor Author

bcmills commented Aug 14, 2023

A racing Chdir in another goroutine would be the most common way to get that sequence, but in that case the Chdir is racing with Open and so you have bigger problems.

Note that the Chdir need not race with Open: it only needs to race with the Info method of the DirEntry structs returned by File.ReadDir.

But I agree that this doesn't seem to arise in real-world use. (I noticed it in the context of thinking about edge-cases while reviewing https://go.dev/cl/518195.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

2 participants