Avoid recursive FileSystemWatcher when not required in PhysicalFilesWatcher#128072
Draft
svick wants to merge 1 commit into
Draft
Avoid recursive FileSystemWatcher when not required in PhysicalFilesWatcher#128072svick wants to merge 1 commit into
svick wants to merge 1 commit into
Conversation
…atcher PhysicalFilesWatcher previously set IncludeSubdirectories=true unconditionally on the wrapped FileSystemWatcher. On Linux this causes inotify watches to be added for every descendant directory under the root, which can be very expensive (or hit inotify limits) when the root is something like / -- as happens with applications launched by systemd with no explicit WorkingDirectory. Now IncludeSubdirectories is enabled only when at least one registered token's pattern actually references a subdirectory (file path contains '/', or wildcard contains '/' or '**'), or when the wrapped FSW watches a strict ancestor of root (where every event is in a subdirectory from the FSW's perspective). The state is maintained via a counter updated when tokens are added or removed, and re-evaluated each time the FSW is enabled. Fixes dotnet#126708 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
|
Tagging subscribers to this area: @dotnet/area-system-io |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR changes Microsoft.Extensions.FileProviders.Physical’s PhysicalFilesWatcher to avoid enabling recursive FileSystemWatcher.IncludeSubdirectories unless it’s actually needed by the registered change-token patterns, reducing the risk of expensive recursive watch setup (notably on Linux/inotify) for common root-only patterns.
Changes:
- Track whether any currently-registered token patterns require subdirectory watching and toggle
IncludeSubdirectoriesaccordingly when enabling the watcher. - Handle the “FSW path is an ancestor of
_root” case by always requiring subdirectory watching. - Add tests validating upgrade/downgrade behavior of
IncludeSubdirectoriesas tokens are added and removed.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs | Introduces _fileWatcherIsAboveRoot and a token counter to conditionally set IncludeSubdirectories in TryEnableFileSystemWatcher, and keeps the counter in sync on add/remove/error paths. |
| src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFilesWatcherTests.cs | Adds unit tests to verify IncludeSubdirectories is enabled only when patterns require it and that it can upgrade/downgrade as tokens come and go. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
This pull request was authored by GitHub Copilot.
PhysicalFilesWatcherpreviously setIncludeSubdirectories = trueunconditionally on the wrappedFileSystemWatcher. On Linux this means inotify watches are created for every descendant directory under the root, which is expensive (and can hit the per-user inotify limit) when the root is something like/— as is the case when an application is launched by systemd without an explicitWorkingDirectory. The default Hosting setup only watchesappsettings.jsonandappsettings.<env>.json, neither of which actually requires recursion.Now
IncludeSubdirectoriesis enabled only when at least one registered token's pattern actually references a subdirectory://or**FileSystemWatcherwatches a strict ancestor of_root(where every event is in a subdirectory from the FSW's perspective)The state is maintained via a small counter that is incremented when a qualifying token is actually added to the lookup and decremented when one is removed (via
ReportChangeForMatchedEntriesorOnError'sCancelAll). The FSW'sIncludeSubdirectoriesis re-evaluated every timeTryEnableFileSystemWatcherruns (which is once perCreateFileChangeTokencall), so the value can both go fromfalsetotrue(when a subdirectory pattern is added) and back tofalse(when subdirectory tokens have all fired and a new root-only token is registered).Fixes #126708.