-
Notifications
You must be signed in to change notification settings - Fork 78
Fix symlink loop performance. #2232
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
Fix symlink loop performance. #2232
Conversation
Package publishing
Documentation at https://github.com/dart-lang/ecosystem/wiki/Publishing-automation. |
PR HealthBreaking changes ✔️
This check can be disabled by tagging the PR with Changelog Entry ✔️
Changes to files need to be accounted for in their respective changelogs. This check can be disabled by tagging the PR with
Coverage
|
| File | Coverage |
|---|---|
| pkgs/watcher/lib/src/directory_watcher/directory_list.dart | 💚 100 % |
| pkgs/watcher/lib/src/directory_watcher/linux.dart | 💔 90 % ⬇️ 2 % |
| pkgs/watcher/lib/src/directory_watcher/mac_os.dart | 💔 0 % ⬇️ NaN % |
| pkgs/watcher/lib/src/directory_watcher/polling.dart | 💚 83 % |
| pkgs/watcher/lib/src/directory_watcher/windows.dart | 💔 0 % ⬇️ NaN % |
| pkgs/watcher/lib/src/utils.dart | 💔 81 % ⬇️ 3 % |
This check for test coverage is informational (issues shown here will not fail the PR).
This check can be disabled by tagging the PR with skip-coverage-check.
API leaks ✔️
The following packages contain symbols visible in the public API, but not exported by the library. Export these symbols or remove them from your publicly visible API.
| Package | Leaked API symbol | Leaking sources |
|---|
This check can be disabled by tagging the PR with skip-leaking-check.
License Headers ✔️
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
| Files |
|---|
| no missing headers |
All source files should start with a license header.
Unrelated files missing license headers
| Files |
|---|
| pkgs/bazel_worker/benchmark/benchmark.dart |
| pkgs/benchmark_harness/integration_test/perf_benchmark_test.dart |
| pkgs/boolean_selector/example/example.dart |
| pkgs/clock/lib/clock.dart |
| pkgs/clock/lib/src/clock.dart |
| pkgs/clock/lib/src/default.dart |
| pkgs/clock/lib/src/stopwatch.dart |
| pkgs/clock/lib/src/utils.dart |
| pkgs/clock/test/clock_test.dart |
| pkgs/clock/test/default_test.dart |
| pkgs/clock/test/stopwatch_test.dart |
| pkgs/clock/test/utils.dart |
| pkgs/coverage/lib/src/coverage_options.dart |
| pkgs/html/example/main.dart |
| pkgs/html/lib/dom.dart |
| pkgs/html/lib/dom_parsing.dart |
| pkgs/html/lib/html_escape.dart |
| pkgs/html/lib/parser.dart |
| pkgs/html/lib/src/constants.dart |
| pkgs/html/lib/src/encoding_parser.dart |
| pkgs/html/lib/src/html_input_stream.dart |
| pkgs/html/lib/src/list_proxy.dart |
| pkgs/html/lib/src/query_selector.dart |
| pkgs/html/lib/src/token.dart |
| pkgs/html/lib/src/tokenizer.dart |
| pkgs/html/lib/src/treebuilder.dart |
| pkgs/html/lib/src/utils.dart |
| pkgs/html/test/dom_test.dart |
| pkgs/html/test/parser_feature_test.dart |
| pkgs/html/test/parser_test.dart |
| pkgs/html/test/query_selector_test.dart |
| pkgs/html/test/selectors/level1_baseline_test.dart |
| pkgs/html/test/selectors/level1_lib.dart |
| pkgs/html/test/selectors/selectors.dart |
| pkgs/html/test/support.dart |
| pkgs/html/test/tokenizer_test.dart |
| pkgs/html/test/trie_test.dart |
| pkgs/html/tool/generate_trie.dart |
| pkgs/pubspec_parse/test/git_uri_test.dart |
| pkgs/stack_trace/example/example.dart |
| pkgs/watcher/test/custom_watcher_factory_test.dart |
| pkgs/yaml_edit/example/example.dart |
This check can be disabled by tagging the PR with skip-license-check.
5d0ad34 to
cd0a497
Compare
Recursively list directories handling symlinks like `find -L`.
cd0a497 to
5a2c806
Compare
|
|
||
| if (targetType == FileSystemEntityType.directory) { | ||
| // Add links to directories with their target to [subdirectories]. | ||
| subdirectories.add(_ResolvedDirectory( |
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.
Does this not end up ignoring link altogether if it is already visited? e.g. if I do:
mkdir tmp/a/b/c
ln -s $PWD/tmp tmp/a/b/c/root
find -L tmp
I get:
tmp
tmp/a
tmp/a/b
tmp/a/b/c
tmp/a/b/c/root
But the current algorithm will just ignore root altogether.
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.
Hmm which find are you using? For me that triggers loop detection and does not print root.
mkdir -p tmp/a/b/c
ln -s $PWD/tmp tmp/a/b/c/root
tmp
tmp/a
tmp/a/b
tmp/a/b/c
find: File system loop detected; ‘tmp/a/b/c/root’ is part of the same file system loop as ‘tmp’.
find --version
find (GNU findutils) 4.10.0
Possibly with your find the loop link is being reported as a link? You could check with -type l. That would be the same way a broken link is reported.
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.
I use Mac OS X find. FWIW tree seems to behave similar, it prints:
tmp
└── a
└── b
└── c
└── root -> /Users/vegorov/tmp
Anyway it's a minor detail.
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.
Thanks.
It's easy to change; but if they're reported here as links then the other code in the package will report them like they're files. Doesn't seem particularly useful.
Kept as-is and added to the listRecursively doc comment instead
/// Skipped links to directories are not mentioned in the directory listing.
Fix #2170
Fix #1728
Use a
Directory.listreplacement that handles symlinks better to avoid severe performance issues with symlink loops on Linux and MacOS.dart-lang/sdk#61407
Use the
find -Lalgorithm, which skips entering a path that's already being traversed. Test using the actualfind -L.Add a simple check for the original performance issue that creates a watcher on a directory with a lot of symlink loops and expects it to start up quickly.