Skip to content

fix: Undisposed FileSystemWatcher in RooIgnoreController (RooIgnoreController_41) #4232

@kiwina

Description

@kiwina

name: Bug Report
description: Undisposed FileSystemWatcher in RooIgnoreController via Task lifecycle
labels: ["bug", "memory-leak", "guaranteed", "core", "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 RooIgnoreController_41)

API Provider

Not Applicable / Other

Model Used

N/A (Core Extension Service - Task/IgnoreController)

🔁 Steps to Reproduce

  1. Setup: Roo Code VS Code extension is active.
  2. Exact actions:
    • A Task instance is created (e.g., by user interaction or an internal process).
    • The Task constructor instantiates RooIgnoreController, which in turn calls setupFileWatcher and creates a vscode.workspace.createFileSystemWatcher.
    • The Task instance is later dereferenced or the extension deactivates without Task.abortTask() (or an equivalent dispose method that handles RooIgnoreController) being called or completing successfully. This could happen if ClineProvider.removeClineFromStack or ClineProvider.dispose has an issue.
  3. What happened after each step:
    • If Task.abortTask() (which calls this.rooIgnoreController?.dispose()) is not executed for the Task instance, the RooIgnoreController's dispose method is not called.
    • Consequently, the FileSystemWatcher created by RooIgnoreController remains active and undisposed.
    • This leads to a resource leak, as the watcher continues to consume system resources.

💥 Outcome Summary

Expected FileSystemWatcher instances created by RooIgnoreController (within a Task) to be reliably disposed of when the Task's lifecycle ends. However, if the Task's cleanup (via abortTask or a dedicated dispose method) is bypassed or fails, the watcher leaks.

📄 Relevant Logs or Errors (Optional)

Summary:

The RooIgnoreController class creates a vscode.workspace.createFileSystemWatcher in its setupFileWatcher method. This watcher is correctly added to an internal this.disposables array, and the RooIgnoreController.dispose() method iterates through this array to dispose of the watcher.
Instances of RooIgnoreController are created within the constructor of the Task class. The Task class has an abortTask method which calls this.rooIgnoreController?.dispose().
A leak is guaranteed if a Task instance is created but its abortTask method ... is not called or does not complete successfully before the Task instance itself is dereferenced or the extension deactivates.

The core issue is the FileSystemWatcher created in src/core/ignore/RooIgnoreController.ts around line 41, which may not be disposed if the owning Task is not properly cleaned up.

Metadata

Metadata

Assignees

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