Re: [PATCH] D30768: [PATCH][VFS] Ignore broken symlinks in the directory iterator.
Nevermind, I see you've fixed. Thanks :) On Fri, Mar 10, 2017 at 3:21 PM Eric Christopherwrote: > Looks like this is failing on a number of bots... > > On Fri, Mar 10, 2017 at 1:37 PM Juergen Ributzka via Phabricator via > cfe-commits wrote: > > ributzka added a comment. > > Thanks Bruno. Committed in r297510. > > > Repository: > rL LLVM > > https://reviews.llvm.org/D30768 > > > > ___ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits > > ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D30768: [PATCH][VFS] Ignore broken symlinks in the directory iterator.
Looks like this is failing on a number of bots... On Fri, Mar 10, 2017 at 1:37 PM Juergen Ributzka via Phabricator via cfe-commitswrote: > ributzka added a comment. > > Thanks Bruno. Committed in r297510. > > > Repository: > rL LLVM > > https://reviews.llvm.org/D30768 > > > > ___ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits > ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D30768: [PATCH][VFS] Ignore broken symlinks in the directory iterator.
ributzka added a comment. Thanks Bruno. Committed in r297510. Repository: rL LLVM https://reviews.llvm.org/D30768 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D30768: [PATCH][VFS] Ignore broken symlinks in the directory iterator.
This revision was automatically updated to reflect the committed changes. Closed by commit rL297510: [VFS] Ignore broken symlinks in the directory iterator. (authored by ributzka). Changed prior to commit: https://reviews.llvm.org/D30768?vs=91371=91403#toc Repository: rL LLVM https://reviews.llvm.org/D30768 Files: cfe/trunk/include/clang/Basic/VirtualFileSystem.h cfe/trunk/lib/Basic/VirtualFileSystem.cpp cfe/trunk/unittests/Basic/VirtualFileSystemTest.cpp Index: cfe/trunk/include/clang/Basic/VirtualFileSystem.h === --- cfe/trunk/include/clang/Basic/VirtualFileSystem.h +++ cfe/trunk/include/clang/Basic/VirtualFileSystem.h @@ -161,7 +161,7 @@ directory_iterator (std::error_code ) { assert(Impl && "attempting to increment past end"); EC = Impl->increment(); -if (EC || !Impl->CurrentEntry.isStatusKnown()) +if (!Impl->CurrentEntry.isStatusKnown()) Impl.reset(); // Normalize the end iterator to Impl == nullptr. return *this; } Index: cfe/trunk/lib/Basic/VirtualFileSystem.cpp === --- cfe/trunk/lib/Basic/VirtualFileSystem.cpp +++ cfe/trunk/lib/Basic/VirtualFileSystem.cpp @@ -246,8 +246,7 @@ if (!EC && Iter != llvm::sys::fs::directory_iterator()) { llvm::sys::fs::file_status S; EC = Iter->status(S); - if (!EC) -CurrentEntry = Status::copyWithNewName(S, Iter->path()); + CurrentEntry = Status::copyWithNewName(S, Iter->path()); } } @@ -1858,7 +1857,7 @@ std::error_code ) : FS(_) { directory_iterator I = FS->dir_begin(Path, EC); - if (!EC && I != directory_iterator()) { + if (I != directory_iterator()) { State = std::make_shared(); State->push(I); } @@ -1871,8 +1870,6 @@ vfs::directory_iterator End; if (State->top()->isDirectory()) { vfs::directory_iterator I = FS->dir_begin(State->top()->getName(), EC); -if (EC) - return *this; if (I != End) { State->push(I); return *this; Index: cfe/trunk/unittests/Basic/VirtualFileSystemTest.cpp === --- cfe/trunk/unittests/Basic/VirtualFileSystemTest.cpp +++ cfe/trunk/unittests/Basic/VirtualFileSystemTest.cpp @@ -305,6 +305,22 @@ } operator StringRef() { return Path.str(); } }; + +struct ScopedLink { + SmallString<128> Path; + ScopedLink(const Twine , const Twine ) { +Path = From.str(); +std::error_code EC = sys::fs::create_link(To, From); +if (EC) + Path = ""; +EXPECT_FALSE(EC); + } + ~ScopedLink() { +if (Path != "") + EXPECT_FALSE(llvm::sys::fs::remove(Path.str())); + } + operator StringRef() { return Path.str(); } +}; } // end anonymous namespace TEST(VirtualFileSystemTest, BasicRealFSIteration) { @@ -334,6 +350,35 @@ EXPECT_EQ(vfs::directory_iterator(), I); } +TEST(VirtualFileSystemTest, BrokenSymlinkRealFSIteration) { + ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/ true); + IntrusiveRefCntPtr FS = vfs::getRealFileSystem(); + + ScopedLink _a("no_such_file", TestDirectory + "/a"); + ScopedDir _b(TestDirectory + "/b"); + ScopedLink _c("no_such_file", TestDirectory + "/c"); + + std::error_code EC; + vfs::directory_iterator I = FS->dir_begin(Twine(TestDirectory), EC); + EXPECT_TRUE(EC); + EXPECT_NE(vfs::directory_iterator(), I); + EC = std::error_code(); + EXPECT_TRUE(I->getName() == _a); + I.increment(EC); + EXPECT_FALSE(EC); + EXPECT_NE(vfs::directory_iterator(), I); + EXPECT_TRUE(I->getName() == _b); + I.increment(EC); + EXPECT_TRUE(EC); + EXPECT_NE(vfs::directory_iterator(), I); + EC = std::error_code(); + EXPECT_NE(vfs::directory_iterator(), I); + EXPECT_TRUE(I->getName() == _c); + I.increment(EC); + EXPECT_FALSE(EC); + EXPECT_EQ(vfs::directory_iterator(), I); +} + TEST(VirtualFileSystemTest, BasicRealFSRecursiveIteration) { ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true); IntrusiveRefCntPtr FS = vfs::getRealFileSystem(); @@ -373,6 +418,44 @@ EXPECT_EQ(1, Counts[3]); // d } +TEST(VirtualFileSystemTest, BrokenSymlinkRealFSRecursiveIteration) { + ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/ true); + IntrusiveRefCntPtr FS = vfs::getRealFileSystem(); + + ScopedLink _a("no_such_file", TestDirectory + "/a"); + ScopedDir _b(TestDirectory + "/b"); + ScopedLink _ba("no_such_file", TestDirectory + "/b/a"); + ScopedDir _bb(TestDirectory + "/b/b"); + ScopedLink _bc("no_such_file", TestDirectory + "/b/c"); + ScopedLink _c("no_such_file", TestDirectory + "/c"); + ScopedDir _d(TestDirectory + "/d"); + ScopedDir _dd(TestDirectory + "/d/d"); + ScopedDir _ddd(TestDirectory + "/d/d/d"); + ScopedLink _e("no_such_file", TestDirectory + "/e"); + + std::vector Contents; + std::error_code EC; + for (vfs::recursive_directory_iterator
[PATCH] D30768: [PATCH][VFS] Ignore broken symlinks in the directory iterator.
bruno accepted this revision. bruno added inline comments. This revision is now accepted and ready to land. Comment at: lib/Basic/VirtualFileSystem.cpp:1873 vfs::directory_iterator I = FS->dir_begin(State->top()->getName(), EC); -if (EC) +if (EC && EC != std::errc::no_such_file_or_directory) return *this; ributzka wrote: > bruno wrote: > > Can you add a comment explaining why you are doing it? I would prefer if we > > reset the `EC` state here than having the callers ignoring `EC` results. > If we reset the EC here, then the caller won't know that there was an issue. > The idea is that we still want the caller to check EC. It should be up to the > caller to decide how to act on this particular error. > > I guess since the caller has to check for the error anyway I could even > remove this check completely and not check EC at all here. Right, this should be fine with the latest changes and per discussions offline. LGTM https://reviews.llvm.org/D30768 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D30768: [PATCH][VFS] Ignore broken symlinks in the directory iterator.
ributzka updated this revision to Diff 91371. ributzka added a comment. Remove the EC check completely. https://reviews.llvm.org/D30768 Files: include/clang/Basic/VirtualFileSystem.h lib/Basic/VirtualFileSystem.cpp unittests/Basic/VirtualFileSystemTest.cpp Index: unittests/Basic/VirtualFileSystemTest.cpp === --- unittests/Basic/VirtualFileSystemTest.cpp +++ unittests/Basic/VirtualFileSystemTest.cpp @@ -305,6 +305,22 @@ } operator StringRef() { return Path.str(); } }; + +struct ScopedLink { + SmallString<128> Path; + ScopedLink(const Twine , const Twine ) { +Path = From.str(); +std::error_code EC = sys::fs::create_link(To, From); +if (EC) + Path = ""; +EXPECT_FALSE(EC); + } + ~ScopedLink() { +if (Path != "") + EXPECT_FALSE(llvm::sys::fs::remove(Path.str())); + } + operator StringRef() { return Path.str(); } +}; } // end anonymous namespace TEST(VirtualFileSystemTest, BasicRealFSIteration) { @@ -334,6 +350,35 @@ EXPECT_EQ(vfs::directory_iterator(), I); } +TEST(VirtualFileSystemTest, BrokenSymlinkRealFSIteration) { + ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/ true); + IntrusiveRefCntPtr FS = vfs::getRealFileSystem(); + + ScopedLink _a("no_such_file", TestDirectory + "/a"); + ScopedDir _b(TestDirectory + "/b"); + ScopedLink _c("no_such_file", TestDirectory + "/c"); + + std::error_code EC; + vfs::directory_iterator I = FS->dir_begin(Twine(TestDirectory), EC); + EXPECT_TRUE(EC); + EXPECT_NE(vfs::directory_iterator(), I); + EC = std::error_code(); + EXPECT_TRUE(I->getName() == _a); + I.increment(EC); + EXPECT_FALSE(EC); + EXPECT_NE(vfs::directory_iterator(), I); + EXPECT_TRUE(I->getName() == _b); + I.increment(EC); + EXPECT_TRUE(EC); + EXPECT_NE(vfs::directory_iterator(), I); + EC = std::error_code(); + EXPECT_NE(vfs::directory_iterator(), I); + EXPECT_TRUE(I->getName() == _c); + I.increment(EC); + EXPECT_FALSE(EC); + EXPECT_EQ(vfs::directory_iterator(), I); +} + TEST(VirtualFileSystemTest, BasicRealFSRecursiveIteration) { ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true); IntrusiveRefCntPtr FS = vfs::getRealFileSystem(); @@ -373,6 +418,44 @@ EXPECT_EQ(1, Counts[3]); // d } +TEST(VirtualFileSystemTest, BrokenSymlinkRealFSRecursiveIteration) { + ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/ true); + IntrusiveRefCntPtr FS = vfs::getRealFileSystem(); + + ScopedLink _a("no_such_file", TestDirectory + "/a"); + ScopedDir _b(TestDirectory + "/b"); + ScopedLink _ba("no_such_file", TestDirectory + "/b/a"); + ScopedDir _bb(TestDirectory + "/b/b"); + ScopedLink _bc("no_such_file", TestDirectory + "/b/c"); + ScopedLink _c("no_such_file", TestDirectory + "/c"); + ScopedDir _d(TestDirectory + "/d"); + ScopedDir _dd(TestDirectory + "/d/d"); + ScopedDir _ddd(TestDirectory + "/d/d/d"); + ScopedLink _e("no_such_file", TestDirectory + "/e"); + + std::vector Contents; + std::error_code EC; + for (vfs::recursive_directory_iterator I(*FS, Twine(TestDirectory), EC), E; + I != E; I.increment(EC)) { +// Skip broken symlinks. +if (EC == std::errc::no_such_file_or_directory) { + EC = std::error_code(); + continue; +} else if (EC) { + break; +} +Contents.push_back(I->getName()); + } + + // Check contents. + EXPECT_EQ(5U, Contents.size()); + EXPECT_TRUE(Contents[0] == _b); + EXPECT_TRUE(Contents[1] == _bb); + EXPECT_TRUE(Contents[2] == _d); + EXPECT_TRUE(Contents[3] == _dd); + EXPECT_TRUE(Contents[4] == _ddd); +} + template static void checkContents(DirIter I, ArrayRef ExpectedOut) { std::error_code EC; Index: lib/Basic/VirtualFileSystem.cpp === --- lib/Basic/VirtualFileSystem.cpp +++ lib/Basic/VirtualFileSystem.cpp @@ -246,8 +246,7 @@ if (!EC && Iter != llvm::sys::fs::directory_iterator()) { llvm::sys::fs::file_status S; EC = Iter->status(S); - if (!EC) -CurrentEntry = Status::copyWithNewName(S, Iter->path()); + CurrentEntry = Status::copyWithNewName(S, Iter->path()); } } @@ -1858,7 +1857,7 @@ std::error_code ) : FS(_) { directory_iterator I = FS->dir_begin(Path, EC); - if (!EC && I != directory_iterator()) { + if (I != directory_iterator()) { State = std::make_shared(); State->push(I); } @@ -1871,8 +1870,6 @@ vfs::directory_iterator End; if (State->top()->isDirectory()) { vfs::directory_iterator I = FS->dir_begin(State->top()->getName(), EC); -if (EC) - return *this; if (I != End) { State->push(I); return *this; Index: include/clang/Basic/VirtualFileSystem.h === --- include/clang/Basic/VirtualFileSystem.h +++ include/clang/Basic/VirtualFileSystem.h @@ -161,7
[PATCH] D30768: [PATCH][VFS] Ignore broken symlinks in the directory iterator.
ributzka added inline comments. Comment at: include/clang/Basic/VirtualFileSystem.h:164 EC = Impl->increment(); -if (EC || !Impl->CurrentEntry.isStatusKnown()) +if (!Impl->CurrentEntry.isStatusKnown()) Impl.reset(); // Normalize the end iterator to Impl == nullptr. bruno wrote: > I would rather we don't drop checks for `EC`s - it's commonly assumed that > whenever they are passed in we wanna check them for errors, can't you just > skip the specific case you want to avoid? EC is an output parameter here. The client is supposed to check it. https://reviews.llvm.org/D30768 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D30768: [PATCH][VFS] Ignore broken symlinks in the directory iterator.
ributzka added inline comments. Comment at: lib/Basic/VirtualFileSystem.cpp:1873 vfs::directory_iterator I = FS->dir_begin(State->top()->getName(), EC); -if (EC) +if (EC && EC != std::errc::no_such_file_or_directory) return *this; bruno wrote: > Can you add a comment explaining why you are doing it? I would prefer if we > reset the `EC` state here than having the callers ignoring `EC` results. If we reset the EC here, then the caller won't know that there was an issue. The idea is that we still want the caller to check EC. It should be up to the caller to decide how to act on this particular error. I guess since the caller has to check for the error anyway I could even remove this check completely and not check EC at all here. https://reviews.llvm.org/D30768 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D30768: [PATCH][VFS] Ignore broken symlinks in the directory iterator.
bruno added a comment. Hi Juergen, Thanks for working on this. Comment at: include/clang/Basic/VirtualFileSystem.h:164 EC = Impl->increment(); -if (EC || !Impl->CurrentEntry.isStatusKnown()) +if (!Impl->CurrentEntry.isStatusKnown()) Impl.reset(); // Normalize the end iterator to Impl == nullptr. I would rather we don't drop checks for `EC`s - it's commonly assumed that whenever they are passed in we wanna check them for errors, can't you just skip the specific case you want to avoid? Comment at: lib/Basic/VirtualFileSystem.cpp:1860 directory_iterator I = FS->dir_begin(Path, EC); - if (!EC && I != directory_iterator()) { + if (I != directory_iterator()) { State = std::make_shared(); Same here. Comment at: lib/Basic/VirtualFileSystem.cpp:1873 vfs::directory_iterator I = FS->dir_begin(State->top()->getName(), EC); -if (EC) +if (EC && EC != std::errc::no_such_file_or_directory) return *this; Can you add a comment explaining why you are doing it? I would prefer if we reset the `EC` state here than having the callers ignoring `EC` results. https://reviews.llvm.org/D30768 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D30768: [PATCH][VFS] Ignore broken symlinks in the directory iterator.
ributzka created this revision. The VFS directory iterator and recursive directory iterator behave differently from the LLVM counterparts. Once the VFS iterators hit a broken symlink they immediately abort. The LLVM counterparts allow to recover from this issue by clearing the error code and skipping to the next entry. This change adds the same functionality to the VFS iterators. There should be no change in current behavior in the current CLANG source base, because all clients have loop exit conditions that also check the error code. https://reviews.llvm.org/D30768 Files: include/clang/Basic/VirtualFileSystem.h lib/Basic/VirtualFileSystem.cpp unittests/Basic/VirtualFileSystemTest.cpp Index: unittests/Basic/VirtualFileSystemTest.cpp === --- unittests/Basic/VirtualFileSystemTest.cpp +++ unittests/Basic/VirtualFileSystemTest.cpp @@ -305,6 +305,22 @@ } operator StringRef() { return Path.str(); } }; + +struct ScopedLink { + SmallString<128> Path; + ScopedLink(const Twine , const Twine ) { +Path = From.str(); +std::error_code EC = sys::fs::create_link(To, From); +if (EC) + Path = ""; +EXPECT_FALSE(EC); + } + ~ScopedLink() { +if (Path != "") + EXPECT_FALSE(llvm::sys::fs::remove(Path.str())); + } + operator StringRef() { return Path.str(); } +}; } // end anonymous namespace TEST(VirtualFileSystemTest, BasicRealFSIteration) { @@ -334,6 +350,35 @@ EXPECT_EQ(vfs::directory_iterator(), I); } +TEST(VirtualFileSystemTest, BrokenSymlinkRealFSIteration) { + ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/ true); + IntrusiveRefCntPtr FS = vfs::getRealFileSystem(); + + ScopedLink _a("no_such_file", TestDirectory + "/a"); + ScopedDir _b(TestDirectory + "/b"); + ScopedLink _c("no_such_file", TestDirectory + "/c"); + + std::error_code EC; + vfs::directory_iterator I = FS->dir_begin(Twine(TestDirectory), EC); + EXPECT_TRUE(EC); + EXPECT_NE(vfs::directory_iterator(), I); + EC = std::error_code(); + EXPECT_TRUE(I->getName() == _a); + I.increment(EC); + EXPECT_FALSE(EC); + EXPECT_NE(vfs::directory_iterator(), I); + EXPECT_TRUE(I->getName() == _b); + I.increment(EC); + EXPECT_TRUE(EC); + EXPECT_NE(vfs::directory_iterator(), I); + EC = std::error_code(); + EXPECT_NE(vfs::directory_iterator(), I); + EXPECT_TRUE(I->getName() == _c); + I.increment(EC); + EXPECT_FALSE(EC); + EXPECT_EQ(vfs::directory_iterator(), I); +} + TEST(VirtualFileSystemTest, BasicRealFSRecursiveIteration) { ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true); IntrusiveRefCntPtr FS = vfs::getRealFileSystem(); @@ -373,6 +418,44 @@ EXPECT_EQ(1, Counts[3]); // d } +TEST(VirtualFileSystemTest, BrokenSymlinkRealFSRecursiveIteration) { + ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/ true); + IntrusiveRefCntPtr FS = vfs::getRealFileSystem(); + + ScopedLink _a("no_such_file", TestDirectory + "/a"); + ScopedDir _b(TestDirectory + "/b"); + ScopedLink _ba("no_such_file", TestDirectory + "/b/a"); + ScopedDir _bb(TestDirectory + "/b/b"); + ScopedLink _bc("no_such_file", TestDirectory + "/b/c"); + ScopedLink _c("no_such_file", TestDirectory + "/c"); + ScopedDir _d(TestDirectory + "/d"); + ScopedDir _dd(TestDirectory + "/d/d"); + ScopedDir _ddd(TestDirectory + "/d/d/d"); + ScopedLink _e("no_such_file", TestDirectory + "/e"); + + std::vector Contents; + std::error_code EC; + for (vfs::recursive_directory_iterator I(*FS, Twine(TestDirectory), EC), E; + I != E; I.increment(EC)) { +// Skip broken symlinks. +if (EC == std::errc::no_such_file_or_directory) { + EC = std::error_code(); + continue; +} else if (EC) { + break; +} +Contents.push_back(I->getName()); + } + + // Check contents. + EXPECT_EQ(5U, Contents.size()); + EXPECT_TRUE(Contents[0] == _b); + EXPECT_TRUE(Contents[1] == _bb); + EXPECT_TRUE(Contents[2] == _d); + EXPECT_TRUE(Contents[3] == _dd); + EXPECT_TRUE(Contents[4] == _ddd); +} + template static void checkContents(DirIter I, ArrayRef ExpectedOut) { std::error_code EC; Index: lib/Basic/VirtualFileSystem.cpp === --- lib/Basic/VirtualFileSystem.cpp +++ lib/Basic/VirtualFileSystem.cpp @@ -246,8 +246,7 @@ if (!EC && Iter != llvm::sys::fs::directory_iterator()) { llvm::sys::fs::file_status S; EC = Iter->status(S); - if (!EC) -CurrentEntry = Status::copyWithNewName(S, Iter->path()); + CurrentEntry = Status::copyWithNewName(S, Iter->path()); } } @@ -1858,7 +1857,7 @@ std::error_code ) : FS(_) { directory_iterator I = FS->dir_begin(Path, EC); - if (!EC && I != directory_iterator()) { + if (I != directory_iterator()) { State = std::make_shared(); State->push(I); } @@ -1871,7 +1870,7 @@