Skip to content

Mitigate macOS FSEvents race in TokensFiredForNewDirectoryContentsOnRename - #135342

Draft
svick wants to merge 1 commit into
dotnet:mainfrom
svick:fix-filewatcher-macos-flaky-test
Draft

svick wants to merge 1 commit into
dotnet:mainfrom
svick:fix-filewatcher-macos-flaky-test

Conversation

@svick

@svick svick commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Summary

Mitigates the flaky Microsoft.Extensions.FileProviders.PhysicalFileProviderTests.TokensFiredForNewDirectoryContentsOnRename test on macOS.

Root cause

The test creates a real directory/subdirectory/file structure on disk, then starts a real FileSystemWatcher-backed PhysicalFilesWatcher/PhysicalFileProvider watch, and asserts the corresponding change tokens have not fired yet (before the test's simulated rename). On macOS, the native watcher is backed by fseventsd, a separate daemon that the process subscribes to asynchronously. As documented by a .NET team member investigating a related issue (#30415 (comment)):

We can get events for operations completed before watcher started... even if we call sync to flush events when watcher is started, we may [see] old events fseventsd did not process yet.

So even though the watcher requests kFSEventStreamEventIdSinceNow, there is no documented guarantee it excludes events for changes made shortly before the stream starts. This occasionally causes the "new directory/subdirectory/file should not have changed yet" assertions to fail.

This is architecturally specific to macOS: Windows (ReadDirectoryChangesW) and Linux (inotify) are handle/descriptor-based with no separate daemon replaying historical events.

Why not fix it in FileSystemWatcher/PhysicalFilesWatcher instead

  • The macOS backend already uses the most responsive options available in the public FSEvents API (kFSEventStreamEventIdSinceNow, 0.0f latency, NoDefer), so there isn't more headroom at that layer.
  • A PhysicalFilesWatcher-side fix (e.g. snapshotting expected state at watch-registration time and suppressing events that predate it) could close this deterministically, but it's a meaningfully more invasive change for a bug class that, in production, results in at most a spurious/redundant change notification — not a missed one or a correctness issue. That cost/benefit doesn't justify it here, so this PR only addresses the test.

Fix

  • Add a short, macOS-only delay between creating the test's directory structure and starting the watcher, reducing the likelihood of the race (not a guaranteed fix — there's no documented bound on the replay window).
  • If the race still occurs for one of the newly created entries' tokens on macOS, treat it as a known/skipped condition (SkipTestException) instead of a hard failure, since it does not indicate a product regression.

Fixes #135283

Note

This PR description and change were drafted with AI (GitHub Copilot) assistance.

…ename

On macOS, fseventsd can occasionally replay directory/file creation
events after the native watcher starts, racing with assertions that
expect no changes to have been reported yet. Add a short delay before
starting the watcher to reduce (not eliminate) the chance of this, and
treat the known race as a skip rather than a failure if it still
occurs for one of the newly created entries.

Fixes dotnet#135283

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b2aac025-5dc1-420e-bfdf-19dd4b2f2f6f
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-extensions-filesystem
See info in area-owners.md if you want to be subscribed.

@svick
svick requested a balanced review from Copilot October 7, 2026 15:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

SkipTestException requires [ConditionalFact]; under [Fact], the race still fails the test.

1 open finding
What changed in this PR

Mitigates a macOS FSEvents race affecting a PhysicalFileProvider rename test.

Changes:

  • Adds a macOS-only delay before watcher registration.
  • Dynamically skips when pre-rename tokens already fired.
File Description
PhysicalFileProviderTests.cs Adds macOS race mitigation and skip handling.

🧠 Review effort: Balanced

if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && changed)
{
// Mark the test as inconclusive/skipped.
throw new SkipTestException($"Known macOS FSEvents race caused the {tokenDescription} token to change before the rename.");

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Microsoft.Extensions.FileProviders.PhysicalFileProviderTests.TokensFiredForNewDirectoryContentsOnRename test fails

2 participants