-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libc++] Fix filesystem::remove_all() on FreeBSD #79540
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
Conversation
@llvm/pr-subscribers-libcxx Author: Mark Johnston (markjdb) ChangesSee the commit message for an explanation. I'm not sure if this bug is the reason for the Full diff: https://github.com/llvm/llvm-project/pull/79540.diff 1 Files Affected:
diff --git a/libcxx/src/filesystem/operations.cpp b/libcxx/src/filesystem/operations.cpp
index 6253d1551b062e..c39a3ee53db439 100644
--- a/libcxx/src/filesystem/operations.cpp
+++ b/libcxx/src/filesystem/operations.cpp
@@ -815,8 +815,10 @@ uintmax_t remove_all_impl(int parent_directory, const path& p, error_code& ec) {
// If opening `p` failed because it wasn't a directory, remove it as
// a normal file instead. Note that `openat()` can return either ENOTDIR
- // or ELOOP depending on the exact reason of the failure.
- if (ec == errc::not_a_directory || ec == errc::too_many_symbolic_link_levels) {
+ // or ELOOP depending on the exact reason of the failure. On FreeBSD it
+ // may return EMLINK instead of ELOOP, contradicting POSIX.
+ if (ec == errc::not_a_directory || ec == errc::too_many_symbolic_link_levels ||
+ ec == errc::too_many_links) {
ec.clear();
if (::unlinkat(parent_directory, p.c_str(), /* flags = */ 0) == -1) {
ec = detail::capture_errno();
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
The XFAIL was added in 7ec6c62 and just captured the current state of the tests in order to stand up the FreeBSD CI instance. It is presumably because of this issue, and assuming the test passes with this change the XFAIL should be removed. |
Do you happen to have a simple recipe to build and run these tests on FreeBSD? I haven't done that before. |
I haven't built upstream llvm in a while, but you should just be able to run e.g. It looks a run with this change should have results here in a bit though: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks reasonable to me but you'll need to remove the XFAIL for the CI to pass. Please also ensure that all the other platforms are green before merging.
remove_all_impl() opens the target path with O_NOFOLLOW, which fails if the target is a symbolic link. On FreeBSD, rather than returning ELOOP, openat() returns EMLINK. This is unlikely to change for compatibility reasons, see https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=214633 . Thus, check for EMLINK as well.
It passes on FreeBSD now that remove_all_impl() handles FreeBSD's non-standard error value when opening a symlink with O_NOFOLLOW.
Thank you. I pushed a second commit which does that. I verified that the test now passes on FreeBSD. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
It looks like one of the test runs was cancelled. Should I try to rerun them? |
All the buildkite stuff at https://buildkite.com/llvm-project/libcxx-ci/builds/33247#_ says "cancelled after 5h" so I think it's probably some VM or container failing to start. No idea what is behind all this infrastructure. :)) |
Not sure about the CI failure, it just seems like a timeout for a VM to start up. Nothing to do with your commit, as usual. |
FWIW while handling DragonFly matches FreeBSD, so the current libc++ code should handle that already. |
This should address a weird segmentation fault issue we have seen during logging shutdown with older versions of the glog library. I'm also disabling symlinks with SetLogSymlink(), to prevent the duplicate "UNKNOWN.INFO" logfile. Doing so also helps with FreeBSD, because there was an issue with std::filesystem::remove_all (used in our unit test) which was fixed only recently, causing it to error out due to the dangling symlinks: llvm/llvm-project#79540 Bug: b/352597329 Change-Id: Ie4faf2740e8eabc7f9dda9127f571084f1a510b3
remove_all_impl() opens the target path with O_NOFOLLOW, which fails if
the target is a symbolic link. On FreeBSD, rather than returning ELOOP,
openat() returns EMLINK. This is unlikely to change for compatibility
reasons, see https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=214633 .
Thus, check for EMLINK as well.