Skip to content

fix: Potential FileSystemWatcher leak in CodeIndexManager (file-watcher_93)Β #4230

@kiwina

Description

@kiwina

name: Bug Report
description: Potential FileSystemWatcher leak in FileWatcher/CodeIndexManager
labels: ["bug", "memory-leak", "guaranteed", "code-index", "auto-generated"]

Thanks for your report! Please check existing issues first:
πŸ‘‰ https://github.com/RooCodeInc/Roo-Code/issues

App Version

N/A (Static Analysis - Detected in file-watcher_93)

API Provider

Not Applicable / Other

Model Used

N/A (Core Extension Service - Code Indexing)

πŸ” Steps to Reproduce

  1. Setup: Roo Code VS Code extension is active.
  2. Exact actions:
    • The FileWatcher class creates a vscode.workspace.createFileSystemWatcher in its initialize method. This watcher is stored in this.fileWatcher.
    • The FileWatcher instance is managed by CodeIndexOrchestrator, which is managed by CodeIndexManager.
    • A scenario occurs where CodeIndexManager.dispose() is not called, or fails to complete, during extension deactivation or due to an unhandled error.
  3. What happened after each step:
    • If CodeIndexManager.dispose() is not successfully executed, the disposal chain (CodeIndexManager -> CodeIndexOrchestrator -> FileWatcher) is broken.
    • The FileSystemWatcher instance within FileWatcher is not disposed.
    • The undisposed watcher continues to consume system resources, leading to a leak.

🚨 Where The Leak Happens - Failure Points
Scenario 1: Error in abortTask()
// If Task.abortTask() throws an error BEFORE reaching this line: this.rooIgnoreController?.dispose(); // This never executes
Scenario 2: ClineProvider Disposal Issues
// If ClineProvider.dispose() doesn't call removeClineFromStack()
// Or if removeClineFromStack() fails before calling cline.abortTask()
// The FileSystemWatcher remains active

Scenario 3: Orphaned Task Instances
// If a Task is created but never added to clineStack
// Or removed from clineStack without proper cleanup
// No disposal path exists

πŸ”§ The Problem Visualized
Task Created β†’ RooIgnoreController Created β†’ FileSystemWatcher Created
↓ ↓ ↓
Task.abortTask() β†’ RooIgnoreController.dispose() β†’ watcher.dispose()
↑ ↑ ↑
MUST BE CALLED MUST BE CALLED MUST HAPPEN

πŸ’₯ Outcome Summary

Expected FileSystemWatcher instances to be reliably disposed of when the extension deactivates or the code indexing feature is stopped. However, if the CodeIndexManager's disposal process is interrupted or skipped, the watcher can leak.

πŸ“„ Relevant Logs or Errors (Optional)

Summary:

The FileWatcher class creates a vscode.workspace.createFileSystemWatcher in its initialize method. The watcher is stored in this.fileWatcher. The dispose method of FileWatcher correctly calls this.fileWatcher?.dispose().

However, the FileWatcher instance itself is managed by CodeIndexOrchestrator, which in turn is managed by CodeIndexManager. If CodeIndexManager.dispose() is not called, or if CodeIndexOrchestrator.stopWatcher() (which calls fileWatcher.dispose()) is not called before the manager is disposed, the FileSystemWatcher will leak.

The CodeIndexManager is a singleton tied to the workspace path and is added to context.subscriptions in src/extension.ts. This means its dispose method should be called on extension deactivation. The leak is guaranteed if there's any scenario where CodeIndexManager.dispose() isn't called or if CodeIndexOrchestrator.stopWatcher() isn't called before the manager's disposal.

The main concern is the FileSystemWatcher created in src/services/code-index/processors/file-watcher.ts around line 93.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue - In ProgressSomeone is actively working on this. Should link to a PR soon.bugSomething isn't working

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions