Skip to content

Option to watch fs events for subdirs separately from root dir#1329

Open
bvinc wants to merge 4 commits into
facebook:mainfrom
bvinc:watch-included-root-dirs-only-upstream
Open

Option to watch fs events for subdirs separately from root dir#1329
bvinc wants to merge 4 commits into
facebook:mainfrom
bvinc:watch-included-root-dirs-only-upstream

Conversation

@bvinc
Copy link
Copy Markdown
Contributor

@bvinc bvinc commented May 27, 2026

This creates a new project setting "watch-included-root-dirs-only" which watches subdirectories at the root level separately. This allows real ignoring of the buck-out folder, which makes the possibility of missing fs change events much less likely.

This is the most important on mac, where fsevent has no knobs to turn, and no way to really ignore the buck-out folder. Without this change, large builds will easily and consistently overflow the internal fsevent buffers and cause file system events to be missed. After this change, almost no events happen, as changes outside of the buck-out folder are rare.

Unfortunately, this requires manual non-recursive polling of the root directory occasionally. I chose to put this in calls to sync2, which usually happen once at the beginning of a build.

bvinc added 3 commits May 27, 2026 11:50
When set, the notify file watcher registers a recursive watch for each
non-ignored top-level subdirectory of the project root rather than a
single recursive watch on the root itself. Ignored top-level directories
(e.g. buck-out) are never registered with the watcher backend.

Defaults to false; existing behavior is unchanged.
When watch-included-root-dirs-only is enabled, `rescan_root` runs on
every sync and tracks (size, mtime) of non-ignored top-level files.
Modifications, creations, and removals at the project root are
synthesized as events and merged into notify's stream. New top-level
directories created mid-session are picked up by the same scan and
registered for recursive watching.

Adds two debug logs:
* a new root subdirectory has a watch registered
* a root-level file was modified
Cover the state transitions: ignored dir filtered at startup, ignored
dir appearing mid-session stays invisible, new top-level dir is reported
with a watch, root file modified/removed, top-level dir removed, no-op
on a clean rescan.
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label May 27, 2026
@meta-codesync
Copy link
Copy Markdown
Contributor

meta-codesync Bot commented May 27, 2026

@facebook-github-bot has imported this pull request. If you are a Meta employee, you can view this in D106542582. (Because this pull request was imported automatically, there will not be any future comments.)

let watch_included_root_dirs_only = root_config
.parse::<bool>(BuckconfigKeyRef {
section: "project",
property: "watch-included-root-dirs-only",
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.

Snake case for buckconfig keys isn't it? Also maybe bike shed it a bit more

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.

I really wish you could grep BuckconfigKeyRef::new and get a big list of all of them to see where you might put a new one and what you might name it. But it ain't so.

`rescan_root` already detects when a previously-watched top-level
subdirectory disappears and emits a synthetic `Remove(Folder)` event,
but the matching `notify` watch was never released. On Linux this is
masked by inotify auto-removing the watch in response to `IN_IGNORED`.
On macOS (fsevent) and Windows (ReadDirectoryChangesW) there is no
such auto-cleanup, so a long-running daemon would slowly leak watch
handles as workspace subdirs are created and destroyed.

Have `rescan_root` return the set of vanished directories alongside
the existing `new_watches`, and unwatch them from `sync2`. Swallow
`WatchNotFound` since it's the expected case on Linux. Bundle the
return values into a `RescanResult` struct so the signature scales
to a future fourth field without breaking call sites.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants