Skip to content

Fix listener leak in terminal tool progress parts, execute strategies, and detached terminals#310157

Merged
meganrogge merged 2 commits into
mainfrom
merogge/leak-fixes
Apr 15, 2026
Merged

Fix listener leak in terminal tool progress parts, execute strategies, and detached terminals#310157
meganrogge merged 2 commits into
mainfrom
merogge/leak-fixes

Conversation

@meganrogge

@meganrogge meganrogge commented Apr 15, 2026

Copy link
Copy Markdown
Collaborator

Fixes #309684
Fixes #309921
Fixes #309923
Fixes #310046

These four issues all report "potential listener LEAK detected, popular" errors from
accumulating too many listeners on shared singleton emitters.

cc @anthonykim1

Copilot AI review requested due to automatic review settings April 15, 2026 15:16
@meganrogge meganrogge self-assigned this Apr 15, 2026
@meganrogge meganrogge added this to the 1.117.0 milestone Apr 15, 2026
@meganrogge
meganrogge enabled auto-merge (squash) April 15, 2026 15:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Fixes multiple “potential listener LEAK detected” reports by preventing per-instance subscriptions to shared singleton emitters across terminal tool progress UI, execute strategies, and detached terminals.

Changes:

  • Register execute()-scoped DisposableStores with execute strategy lifetimes so Event.toPromise listeners are cleaned up on early disposal.
  • Add a detached mode to XtermTerminal to skip global singleton listeners, and centralize theme/config propagation in TerminalService.
  • Replace MenuWorkbenchToolBar in ChatTerminalToolProgressPart with an ActionBar rebuilt from internal state instead of context keys/menus.
Show a summary per file
File Description
src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/executeStrategy/richExecuteStrategy.ts Registers DisposableStore with strategy lifetime to avoid lingering listeners on early disposal.
src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/executeStrategy/basicExecuteStrategy.ts Same as above for basic strategy execution.
src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts Introduces detached option to skip global listeners; adds updateTheme() for external updates.
src/vs/workbench/contrib/terminal/browser/terminalService.ts Centralizes theme/config listeners for detached terminals and forwards updates to all instances.
src/vs/workbench/contrib/terminal/browser/terminal.ts Extends detached xterm interface with updateConfig() / updateTheme().
src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatTerminalToolProgressPart.ts Replaces menu/context-key-driven toolbar with rebuilt ActionBar actions to avoid listener buildup.

Copilot's findings

Comments suppressed due to low confidence (1)

src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatTerminalToolProgressPart.ts:1

  • _toolbarOutputExpanded is only updated in _toggleOutput(...), but _updateToolbarContextKeys(...) can change the output expansion state indirectly (eg via _maybeAutoExpandTerminalOutput(...) or initial restored state). That can leave the toolbar toggle icon/label out of sync with this._outputView.isExpanded. Consider setting _toolbarOutputExpanded = this._outputView.isExpanded inside _updateToolbarContextKeys(...) before calling _updateToolbarActions(), and also explicitly resetting it when _usesCollapsibleWrapper is true to avoid stale state.
/*---------------------------------------------------------------------------------------------
  • Files reviewed: 6/6 changed files
  • Comments generated: 7

Comment thread src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts Outdated
Comment thread src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts
Comment thread src/vs/workbench/contrib/terminal/browser/terminalService.ts Outdated
@github-actions

Copy link
Copy Markdown
Contributor

Screenshot Changes

Base: 938197bd Current: 9d222f5e

Changed (1)

editor/inlineCompletions/other/JumpToHint/Dark
Before After
before after

@meganrogge
meganrogge merged commit 8379a04 into main Apr 15, 2026
26 checks passed
@meganrogge
meganrogge deleted the merogge/leak-fixes branch April 15, 2026 16:15
meganrogge added a commit that referenced this pull request Apr 29, 2026
…13369)

Each execute() call registered a per-call DisposableStore via
this._register(store), but store.dispose() in the finally block does
not remove the reference from the parent _toDispose Set. Stale,
already-disposed stores accumulated across invocations on long-lived
strategies (28 observed in the wild).

Track in-flight stores in a dedicated _executionStores DisposableStore
and delete(store) on completion. Preserves the mid-flight disposal
cleanup from #310157 while clearing the reference on the happy path.

Fixes #313368
@vs-code-engineering vs-code-engineering Bot locked and limited conversation to collaborators May 30, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.