Conversation
shulaoda
force-pushed
the
09-24-feat_track_a_path_through_every_ancestor
branch
3 times, most recently
from
September 24, 2026 10:00
0a7754b to
fa6dc9c
Compare
shulaoda
force-pushed
the
09-24-feat_track_a_path_through_every_ancestor
branch
from
September 24, 2026 10:11
fa6dc9c to
f07fa4e
Compare
…andles other roots need
…ase the chain of a missing root on unwatch
…a returning root once
… and rebuild only on change
…ies renaming a directory with an open handle below it
…andle cannot be opened
8 of 15 tasks
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.
A
TrackPathwatch now follows its path through every ancestor, on every backend:This is what FSEvents'
WatchRootdoes natively. Before, inotify and kqueue dropped the watch of a moved ancestor and never re-armed it (kqueue only kept stale fds because its recursive removal walked the disk), Windows ignored the ancestor's event and never opened a handle for a tracked directory that appeared later, and FSEvents suppressed theROOT_CHANGEDthat says the root is back.Per backend:
CREATE | DELETE | MOVED_FROM | MOVED_TO), shared and ref-counted; the parent keeps the full mask.vanish_below/rearm_belowrun on ancestor events.NOTE_LINKre-adds only under recursive roots.ROOT_CHANGEDwith the root present is reported asCreate. FSEvents skips thatROOT_CHANGEDwhen the root comes back within a few milliseconds of going (probe: ~25% of the time under load, never with a 20 ms gap), so a root that went is looked at again 200 ms and 2 s later and reported as created if it is back; whichever side sees it first reports it, the other stays quiet.Closes #32. Tests added per backend;
get_watch_handles()leaves out the ancestor-only watches.Fixes after review
A review of this PR (56 confirmed findings, then three review rounds of the fixes) is folded into the five
fix(...)anddocscommits on top. What changed, per backend:Errthrough the handler and armed again by watching it again..., hard links) shares one watch descriptor; every spelling a watched path covers is now reported, with the kernel mask being the union of the spellings' masks and each spelling filtered to what it asked for. A new directory below several spellings is walked once.watchandunwatchare indexed (unwatching 10k roots: ~200 ms). An ancestor that cannot be examined (EACCES, ELOOP) failswatchinstead of waiting. ANoTrackfile that was reported through its parent's watch is dropped withRemove(File)when the parent moves (see theTargetMode::NoTrackdocs).check_chainfollows an ancestor that is a symlink to a directory and acts only when presence changes; unwatching a missing root returnsOkand releases the ancestor chain;NOTE_LINKno longer drops a recursiveNoTrackroot; a root created between its stat and the kevent registration is caught; the entry fds of a non-recursive directory root are released on unwatch.max_fsevent_paths, nested under another watched root, below directories that do not exist yet) are checked from the disk whenever a directory above them is created, removed or renamed, and reportedRemove(Any)/Createwithroot changed. A root that comes back is reported once (the mark is bound to the file's inode).NoTrackroots get noroot changedCreate. For a root two or more levels below missing directories, the deepest existing ancestor (at least three directories deep) is watched until the next stream rebuild. The look-again thread sleeps on aCondvarand is joined onDrop.watch/commit; handles are rebuilt only when a root's presence or an ancestor's existence changed; only the entry whose own directory cannot be opened fails; re-watching a missing root reportsCreate. These changes ran only on CI (no Windows host here).108 tests were added across the four backends. Known limits are listed in the
TargetMode::TrackPathdocs: a symlink retargeted in place (ln -sfn) is not noticed; FSEvents may miss folded roots when a directory is swapped or goes and comes back within milliseconds; anchors are computed at stream rebuild;notify-debouncer-fullpairs a rename across spellings when a directory has several.Note: the entries in the root
CHANGELOG.mddescribe the change for upstream readers; the fork's release notes come fromnotify/CHANGELOG.mdand the commit titles.