Skip to content

Duplicate Terminal Shell Execution Handlers Causing Event ConflictsΒ #1364

@KJ7LNW

Description

@KJ7LNW

Which version of the app are you using?

3.7.12+

Which API Provider are you using?

Anthropic

Which Model are you using?

Claude 3.7 Sonnet

What happened?

Multiple instances of TerminalManager are being created across different contexts in the application (one during extension activation in src/activate/registerTerminalActions.ts and one per active task/Roo webview). Each TerminalManager instance registers its own shell execution event handlers, leading to duplicate event handling.

When a terminal command is executed, the shell execution events (onDidStartTerminalShellExecution and onDidEndTerminalShellExecution) are being handled multiple times by different TerminalManager instances. This causes:

  1. Redundant processing of the same events
  2. Potential race conditions when multiple handlers try to update the same terminal state
  3. Inconsistent terminal ownership with ambiguity about which manager is responsible for resource cleanup

Steps to reproduce

  1. Run sleep 30 in one Roo instance
  2. Click "open in editor" to launch a second Roo instance
  3. Run sleep 30 in the second instance
  4. One of the commands will complete normally, but the other will hang indefinitely

Additional context

I have verified this by adding debug to the handlers that print duplicate records even for running a single command because every call to new TerminalManager registers the handlers again.

Terminal Architecture Refactoring

I am working on a pull request to redesign terminal integration handling as follows:

Hierarchy

  • TerminalRegistry (static, global): Manages all terminals
  • Terminal (class): Encapsulates VSCode terminal with ownership and state
  • TerminalProcess (class): Represents a command execution within a terminal

Key Components

TerminalRegistry

  • Singleton for global terminal management
  • Centralized shell execution event handling
  • Terminal creation, lookup, and task-based management
  • Methods: getOrCreateTerminal, releaseTerminalsForTask, registerShellExecutionHandlers

Terminal

  • Replaces TerminalInfo interface with proper class
  • Manages single terminal instance with taskId ownership
  • Handles command execution and process lifecycle
  • Prevents concurrent command execution
  • Methods: runCommand, claim, release, handleStreamAvailable, handleShellExecutionComplete

TerminalProcess

  • Enhanced with stream handling
  • Responsible for command execution state and results
  • Exit code interpretation moved from TerminalManager

TerminalManager

TerminalManager is deprecated and removed because it is the problem child which causes terminal ownership confusion between instances

Command Execution Flow

  1. Cline obtains terminal via TerminalRegistry.getOrCreateTerminal(taskId, cwd)
  2. Terminal.runCommand(command) creates TerminalProcess
  3. Shell execution events routed through TerminalRegistry to Terminal to TerminalProcess
  4. Process completion handled at appropriate level

Multiple Cline Webview Support

  • Global TerminalRegistry enables multiple Cline webview instances to share terminals
  • Each Cline instance interacts with TerminalRegistry directly
  • Terminal ownership tracked by taskId prevents conflicts between instances
  • Shell execution events properly routed to correct Terminal/TerminalProcess regardless of source

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