Skip to content

Commit 6f21103

Browse files
authored
fix: Prevent FileSystemWatcher leak in RooIgnoreController (#4233)
* fix: auto patch for RooIgnoreController_41 * fix: improve error handling during task disposal and cleanup
1 parent c02e01e commit 6f21103

File tree

1 file changed

+64
-20
lines changed

1 file changed

+64
-20
lines changed

src/core/task/Task.ts

Lines changed: 64 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,59 @@ export class Task extends EventEmitter<ClineEvents> {
977977
await this.initiateTaskLoop(newUserContent)
978978
}
979979

980+
public dispose(): void {
981+
// Stop waiting for child task completion.
982+
if (this.pauseInterval) {
983+
clearInterval(this.pauseInterval)
984+
this.pauseInterval = undefined
985+
}
986+
987+
// Release any terminals associated with this task.
988+
try {
989+
// Release any terminals associated with this task.
990+
TerminalRegistry.releaseTerminalsForTask(this.taskId)
991+
} catch (error) {
992+
console.error("Error releasing terminals:", error)
993+
}
994+
995+
try {
996+
this.urlContentFetcher.closeBrowser()
997+
} catch (error) {
998+
console.error("Error closing URL content fetcher browser:", error)
999+
}
1000+
1001+
try {
1002+
this.browserSession.closeBrowser()
1003+
} catch (error) {
1004+
console.error("Error closing browser session:", error)
1005+
}
1006+
1007+
try {
1008+
if (this.rooIgnoreController) {
1009+
this.rooIgnoreController.dispose()
1010+
this.rooIgnoreController = undefined
1011+
}
1012+
} catch (error) {
1013+
console.error("Error disposing RooIgnoreController:", error)
1014+
// This is the critical one for the leak fix
1015+
}
1016+
1017+
try {
1018+
this.fileContextTracker.dispose()
1019+
} catch (error) {
1020+
console.error("Error disposing file context tracker:", error)
1021+
}
1022+
1023+
try {
1024+
// If we're not streaming then `abortStream` won't be called
1025+
if (this.isStreaming && this.diffViewProvider.isEditing) {
1026+
this.diffViewProvider.revertChanges().catch(console.error)
1027+
}
1028+
} catch (error) {
1029+
console.error("Error reverting diff changes:", error)
1030+
}
1031+
}
1032+
9801033
public async abortTask(isAbandoned = false) {
9811034
console.log(`[subtasks] aborting task ${this.taskId}.${this.instanceId}`)
9821035

@@ -988,28 +1041,19 @@ export class Task extends EventEmitter<ClineEvents> {
9881041
this.abort = true
9891042
this.emit("taskAborted")
9901043

991-
// Stop waiting for child task completion.
992-
if (this.pauseInterval) {
993-
clearInterval(this.pauseInterval)
994-
this.pauseInterval = undefined
995-
}
996-
997-
// Release any terminals associated with this task.
998-
TerminalRegistry.releaseTerminalsForTask(this.taskId)
999-
1000-
this.urlContentFetcher.closeBrowser()
1001-
this.browserSession.closeBrowser()
1002-
this.rooIgnoreController?.dispose()
1003-
this.fileContextTracker.dispose()
1004-
1005-
// If we're not streaming then `abortStream` (which reverts the diff
1006-
// view changes) won't be called, so we need to revert the changes here.
1007-
if (this.isStreaming && this.diffViewProvider.isEditing) {
1008-
await this.diffViewProvider.revertChanges()
1044+
try {
1045+
this.dispose() // Call the centralized dispose method
1046+
} catch (error) {
1047+
console.error(`Error during task ${this.taskId}.${this.instanceId} disposal:`, error)
1048+
// Don't rethrow - we want abort to always succeed
10091049
}
1010-
10111050
// Save the countdown message in the automatic retry or other content.
1012-
await this.saveClineMessages()
1051+
try {
1052+
// Save the countdown message in the automatic retry or other content.
1053+
await this.saveClineMessages()
1054+
} catch (error) {
1055+
console.error(`Error saving messages during abort for task ${this.taskId}.${this.instanceId}:`, error)
1056+
}
10131057
}
10141058

10151059
// Used when a sub-task is launched and the parent task is waiting for it to

0 commit comments

Comments
 (0)