Skip to content

fix(watcher): update notify to rc.8 to fix macOS root-switch hangs - #939

Merged
dkovalenko-oai merged 3 commits into
mainfrom
triage-bot/issue-938
Nov 11, 2026
Merged

dkovalenko-oai merged 3 commits into
mainfrom
triage-bot/issue-938

Conversation

@gustav-fff

@gustav-fff gustav-fff commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

Update notify to 9.0.0-rc.8 to fix the macOS watcher hang when Neovim switches search roots in quick succession. The release also skips redundant metadata reads when FFF registers directory watches on Linux.

Closes #938.


macOS watcher fix · Linux watch registration change

Summary by CodeRabbit

  • Chores
    • This update contains internal maintenance only. No changes to the app’s features, behavior, interface, or workflows are included, so there are no new capabilities or user-facing fixes to call out. Existing functionality remains unchanged, and no action is needed.

notify's FsEventWatcher restarts its stream on every watch() and can lose
a CFRunLoopStop issued right after a start, leaving the caller in
pthread_join forever. create_debouncer hit that twice per watcher
(base, .git, .git/logs). Register all paths with one update_paths call
on recursive backends.

The stuck pool worker then deadlocked every later scan through the
blocking BACKGROUND_THREAD_POOL.broadcast in hint_allocator_collect and
release_thread_buffers. Use spawn_broadcast so cleanup never waits on a
busy worker.

Closes #938

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your trial has ended. Reactivate Greptile to resume code reviews.

@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

The workspace updates its shared notify dependency from 9.0.0-rc.3 to 9.0.0-rc.8.

Changes: Notify dependency update

Layer / File(s) Summary
Update shared dependency version
Cargo.toml
The shared notify dependency version changes to 9.0.0-rc.8.

Estimated code review effort: 1 (Trivial) | ~3 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: dmtrkovalenko

Merge Risk: Minimal · up to d769f

The dependency update addresses the reported watcher race; no merge-blocking regression was established.

Pre-merge checks: Passed 3 · Inconclusive 1

Failed Failed checks: 1 inconclusive

Check name Status Explanation Resolution
Linked Issues check Inconclusive The whole-PR summary shows only a notify upgrade from 9.0.0-rc.3 to 9.0.0-rc.8. The PR description says this fixes the macOS watcher hang in [#938], but the available evidence does not establish… Evidence that notify 9.0.0-rc.8 fixes the macOS watcher hang described in [#938] is needed to decide compliance.
Passed Passed checks: 3 passed

Check name Status Explanation
Title check Passed The title clearly names the notify upgrade and the macOS root-switch hang it aims to fix.
Out of Scope Changes check Passed The only summarized code change upgrades notify. This directly targets the watcher hang in [#938]. The Linux watch-registration improvement is an incidental benefit of the same dependency upgrade, n…
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Full details: Out of Scope Changes check

Explanation

The only summarized code change upgrades notify. This directly targets the watcher hang in [#938]. The Linux watch-registration improvement is an incidental benefit of the same dependency upgrade, not a separate unrelated code change.

Full details: Linked Issues check

Explanation

The whole-PR summary shows only a notify upgrade from 9.0.0-rc.3 to 9.0.0-rc.8. The PR description says this fixes the macOS watcher hang in [#938], but the available evidence does not establish that rc.8 contains that fix. The separate API initialization problem is not a requirement for this change.

Resolution

Evidence that notify 9.0.0-rc.8 fixes the macOS watcher hang described in [#938] is needed to decide compliance.

Finishing Touches

Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Recent review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1b93c65a-de9b-4d08-99f0-800794b30bbd
Commits

Reviewing files that changed from the base of the PR and between 0b349fd and d769f2d.

Files ignored due to path filters: 1

  • Cargo.lock is excluded by !**/*.lock
Files selected for processing: 1

  • Cargo.toml

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

// The .git directory is excluded from the file list but we still need
// to observe changes that affect git status (staging, unstaging,
// committing, branch switches, merges, etc)
watch_git_status_paths(&mut debouncer, git_workdir.as_ref());

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

@gustav-fff wtf wy did yo do that? this was the code I wrote to avoid watching git internals this exceeds fs events and inotify limits

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

[triage-bot] DIRECTED: Nothing new is watched. Watched set is the same as on main: base + .git NonRecursive + .git/logs NonRecursive. No .git recursion was added.

The diff shows watch_git_status_paths as deleted, but it was only split:

  • git_status_paths (background_watcher.rs:1042) is the same function with the same is_dir checks and the same two paths. It just returns them instead of calling watch().
  • Linux/inotify (:308): same watch(path, NonRecursive) loop, same position after the per-dir watches. Same behavior.
  • macOS/Windows (:246): the same two paths go into one update_paths with the base, as PathOp::watch_non_recursive. In notify 9.0.0-rc.4, FsEventWatcher::update_paths_inner runs append_path(path, config.recursive_mode()) for each op, between one stop() and one run(). Before, it ran 3 watch() calls, so 3 stop/run cycles, and each cycle can hit the [Suggestion]: pause git status work while the picker UI is closed #942 hang. The final stream has the same 3 paths with the same is_recursive flags. Windows uses the default update_paths, which calls watch() in a loop, so nothing changes there.

One real difference: if .git fails in the batch, .git/logs is skipped (remaining is dropped). Before, each path was tried separately. Only warn! either way.

If you want the old watch_git_status_paths shape kept for the inotify branch and only the FSEvents call batched, say so and I'll push it.

Honk-Honk 🪿

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

@gustav-fff yes please get rid of this uselles vec allocation

@gustav-fff gustav-fff Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

[triage-bot] DIRECTED: Pushed 0b349fd. Both Vecs are gone.

  • git_status_paths (background_watcher.rs:1044) returns impl Iterator<Item = PathBuf>, built from Option<.git>.chain(Option<.git/logs>). Same is_dir checks, no heap.
  • FSEvents (:240): iter::once(base).chain(git_status_paths(..).map(PathOp::watch_non_recursive)) goes straight into update_paths. No ops Vec on our side.
  • inotify (:306): watch_git_status_paths(&mut debouncer, git_workdir.as_ref()) is back, same shape as before.

The one Vec left is in fff-notify-debouncer-full::update_paths (lib.rs:674), because notify's Watcher::update_paths takes Vec<PathOp>. That is the API. It runs once per watcher.

make lint-rust clean, cargo fmt --check clean, make test-rust 0 failed.

Honk-Honk 🪿

git_status_paths now returns an Option-chain iterator, the FSEvents batch
chains it straight into update_paths, and the inotify branch goes back to
watch_git_status_paths.
@dkovalenko-oai dkovalenko-oai changed the title fix: batch FSEvents watches and stop blocking pool broadcasts (#938) fix(watcher): update notify to rc.8 to fix macOS root-switch hangs Nov 11, 2026
@dkovalenko-oai
dkovalenko-oai merged commit 8a29cfd into main Nov 11, 2026
51 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Changing the indexed root intermittently hangs the new scan forever (nvim, change_indexing_directory)

3 participants