This is an archive of the discontinued LLVM Phabricator instance.

[llvm][vfs] Avoid silent fallback to process-wide working directory
ClosedPublic

Authored by benlangmuir on Apr 25 2023, 11:10 AM.

Details

Summary

In createPhysicalFileSystem, preserve the per-instance working directory, even after the first call to getcwd fails.

rdar://108213753

Diff Detail

Event Timeline

benlangmuir created this revision.Apr 25 2023, 11:10 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 25 2023, 11:10 AM
Herald added a subscriber: hiraditya. · View Herald Transcript
benlangmuir requested review of this revision.Apr 25 2023, 11:10 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 25 2023, 11:10 AM
owenv accepted this revision.Apr 25 2023, 12:36 PM

LGTM thanks! But please get a second review from someone more familiar with this code

This revision is now accepted and ready to land.Apr 25 2023, 12:36 PM
jansvoboda11 accepted this revision.May 1 2023, 10:52 AM

This is a step in the right direction, so LGTM.

But I think it would be nicer to fail earlier (in the constructor), or propagate the error out of adjustPath(). What do you think? Would be nice to add a FIXME for this.

But I think it would be nicer to fail earlier (in the constructor), or propagate the error out of adjustPath(). What do you think?

Returning an error from adjustPath makes sense to me if we don't have a usable WD, but the constructor is not so obvious. I could see a few options

  • Pass a std::error_code out parameter, but still construct the filesystem so you can ignore the error if desired -- we certainly don't care about the error in clang-scan-deps since we are going to set our own WD later.
  • Remove the getcwd call and require passing in an initial WD string. This doesn't really match how we use the filesystem in scan-deps, because we have a per-TU working directory not per-TU filesystem, so I think this could be awkward, or we end up doing something silly like passing "/"
  • Don't set any initial working directory in the constructor and reject any calls using relative paths until one is provided via setCurrentWorkingDirectory.
This revision was landed with ongoing or failed builds.May 2 2023, 9:39 AM
This revision was automatically updated to reflect the committed changes.
ro added a subscriber: ro.May 3 2023, 6:51 AM

The new test FAILs on Solaris like so:

FAIL: LLVM-Unit :: Support/./SupportTests/12/42 (70024 of 75206)
[...]
/var/llvm/dist-amd64-release-stage2-A-flang/tools/clang/stage2-bins/unittests/Support/./SupportTests --gtest_filter=VirtualFileSystemTest.PhysicalFileSystemWorkingDirFailure
--
/vol/llvm/src/llvm-project/dist/llvm/unittests/Support/VirtualFileSystemTest.cpp:546: Failure
Expected equality of these values:
  FS1->getCurrentWorkingDirectory().getError()
    Which is: system:0
  errc::no_such_file_or_directory
    Which is: 4-byte object <02-00 00-00>

Running it under truss (the Solaris equivalent of strace), one sees

24717:  unlinkat(AT_FDCWD, "/var/tmp/d1-67ee3b", AT_REMOVEDIR) Err#22 EINVAL

As documented in rmdir(2), this is expected:

EINVAL          The  directory  to be removed is the current directory,
                or the final component of path is ".".

This is left unspecified in XPG7; however in case there is an error, it's expected to be EBUSY. I suspect Solaris kept EINVAL for backwards compatibility.

@ro thanks for letting me know; this should skip the test if the removal fails: https://reviews.llvm.org/D149760. I looked to see if there was another way to get getcwd to fail inside createPhysicalFileSystem but it seems the only other idea would be EACCESS, but I see a note "This is only checked in limited cases, depending on implementation details." so it doesn't seem like a great choice either.