Skip to content

Linux: file watcher never covers directory trees created after startup (@parcel/watcher inotify gap) #17955

Description

@safisa

Bug Description:

On Linux, @parcel/watcher's inotify backend needs one watch per directory. The initial subscribe() walks the tree recursively, but a directory that appears later only gets a watch on itself (InotifyBackend::handleSubscriptionwatchDir, no scan of its contents). Anything already inside it at that moment never gets a watch for the rest of the backend's life — and that is the normal case for mkdir -p, git checkout, unzip/import or a tree renamed into the workspace, because the next level is created microseconds after its parent. Edits under such a subtree never reach editors, the navigator or language servers (didChangeWatchedFiles) until the backend restarts. No error, no log line.

Upstream: parcel-bundler/watcher#97 (open since 2022, from microsoft/vscode#142694 — VS Code closed it as upstream and has no workaround; a window reload heals it) and parcel-bundler/watcher#243. It was noted when Theia moved from nsfw to parcel (#12784) but never tracked here.

Measured (inotify census via /proc/<pid>/fdinfo): child dir created 0 ms after its parent → 0/10 watched, ≥ 0.5 ms → 10/10; mkdir -p of a 21-dir tree → 9–12 watched in 6/6 trials; a complete tree rename()d in → 1/21; git checkout adding a folder → 5/11 dark.

Note for workarounds: FileService.watch(newDir, { recursive: true }) does not re-arm the subtree — since #17017 it is subsumed by the workspace-root watcher and never reaches the backend. Only a provider-level watch (RemoteFileSystemProvider.watchDiskFileSystemProvider.watch) creates a fresh parcel subscription; that is what we do downstream for known subtrees, at the price of duplicate events for them.

Steps to Reproduce:

  1. On Linux, start examples/browser on an empty workspace folder.
  2. In a terminal: mkdir -p 1/2/3/4 && echo a > 1/2/3/4/f.txt; open f.txt in the editor.
  3. echo b >> 1/2/3/4/f.txt → the editor does not update and the explorer/SCM never reflect changes under 1/2. Restarting the backend fixes it (full re-walk).

Additional Information

  • The fix belongs upstream: handleSubscription should scan a newly created directory and watch its subdirectories after watchDir; we intend to propose it. Theia ships parcel's prebuilt binaries, so a Theia-side mitigation would be: on a directory create event, subscribe a nested parcel watcher for it (recursive walk) and dedupe the doubled events — refactor(filesystem): serve both kinds of watching through one interface #17944 looks like the natural place.
  • Unrelated to max_user_watches (12% used) and to files.watcherExclude: a watch that was never installed cannot be restored by excludes. macOS (FSEvents) and Windows (ReadDirectoryChangesW) are unaffected, so it does not reproduce on most dev machines.
  • Operating System: Linux 6.12 (RHEL/Ubuntu in the upstream reports), Node 24, @parcel/watcher 2.6.0
  • Theia Version: 1.74.1 (also 1.73.1)

Metadata

Metadata

Assignees

No one assigned

    Labels

    OS/Linuxissues related to the Linux OSbugbugs found in the applicationfile-watchersissues related to filesystem watchers - @parcel/watcherfilesystemissues related to the filesystemhelp wantedissues meant to be picked up, require help

    Type

    No type

    Projects

    Status
    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions