Skip to content

Comments

fix(tui): terminate cleanly when terminal closes#610

Open
Olusammytee wants to merge 1 commit intoKilo-Org:devfrom
Olusammytee:fix/159-tui-shutdown-on-stdio-close
Open

fix(tui): terminate cleanly when terminal closes#610
Olusammytee wants to merge 1 commit intoKilo-Org:devfrom
Olusammytee:fix/159-tui-shutdown-on-stdio-close

Conversation

@Olusammytee
Copy link
Contributor

Summary

  • add one-shot shutdown hooks for SIGINT/SIGHUP/SIGTERM and parent disconnect
  • trigger shutdown when stdin closes/ends (common when VS Code terminal is closed)
  • guard shutdown to run only once and avoid duplicate RPC calls

Fixes #159

Copilot AI review requested due to automatic review settings February 22, 2026 18:43
@github-actions
Copy link
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

process.on("SIGTERM", shutdown)
process.once("SIGHUP", shutdown)
process.once("SIGTERM", shutdown)
process.once("SIGINT", shutdown)
Copy link
Contributor

Choose a reason for hiding this comment

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

WARNING: Handling SIGINT here may conflict with the TUI's own Ctrl+C handling.

The TUI (ink-based) typically intercepts SIGINT to manage its own exit flow (e.g., prompting to confirm exit, cleaning up the terminal). By registering process.once("SIGINT", shutdown) at this level, the signal handler will call client.call("shutdown") immediately when the user presses Ctrl+C, potentially racing with or bypassing the TUI's normal onExit cleanup path (line 188-190).

Consider removing the SIGINT handler and relying on the TUI's existing onExit callback for user-initiated exits. The other signal handlers (SIGHUP, SIGTERM, disconnect, stdin close) are appropriate for external/non-interactive termination scenarios.

@kiloconnect
Copy link
Contributor

kiloconnect bot commented Feb 22, 2026

Code Review Summary

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
packages/opencode/src/cli/cmd/tui/thread.ts 139 SIGINT handler may conflict with TUI's own Ctrl+C exit flow
packages/opencode/src/cli/cmd/tui/thread.ts 188-190 onExit callback calls client.call("shutdown") directly without the shuttingDown guard, allowing a double shutdown call
Other Observations (not in diff)

Issues found in unchanged code that cannot receive inline comments:

File Line Issue
packages/opencode/src/cli/cmd/tui/thread.ts 188-190 The onExit callback calls client.call("shutdown", undefined) directly without going through the shuttingDown guard. If a signal triggers shutdown() first (setting shuttingDown = true), and then the TUI exits normally via onExit, it will call client.call("shutdown") a second time. The onExit handler should either call the shared shutdown function or check the shuttingDown flag to avoid a redundant RPC call.
Files Reviewed (1 files)
  • packages/opencode/src/cli/cmd/tui/thread.ts - 2 issues

Fix these issues in Kilo Cloud

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request adds graceful shutdown handling to the TUI command to fix issue #159, where the CLI process remains in memory after closing a VS Code terminal. The changes register shutdown hooks for various termination signals and stdin closure events, with a guard to prevent duplicate shutdown calls.

Changes:

  • Added shutdown handlers for SIGINT, SIGHUP, SIGTERM, and parent disconnect signals
  • Added stdin close/end event handlers to detect terminal closure
  • Implemented a shuttingDown flag to prevent duplicate RPC shutdown calls

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +141 to +142
process.stdin.once("end", shutdown)
process.stdin.once("close", shutdown)
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

The stdin event listeners may cause premature shutdown when stdin is piped. On line 146, Bun.stdin.text() reads stdin completely when !process.stdin.isTTY, which will trigger the "end" event immediately after reading. This means the TUI would shut down right after starting when input is piped.

Consider registering the stdin event handlers only when process.stdin.isTTY is true, or register them after the stdin read at line 146 completes.

Suggested change
process.stdin.once("end", shutdown)
process.stdin.once("close", shutdown)
if (process.stdin.isTTY) {
process.stdin.once("end", shutdown)
process.stdin.once("close", shutdown)
}

Copilot uses AI. Check for mistakes.
Comment on lines +137 to +139
process.once("SIGHUP", shutdown)
process.once("SIGTERM", shutdown)
process.once("SIGINT", shutdown)
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

The use of process.once() here is inconsistent with the existing signal handlers in the codebase. The serve and web commands (packages/opencode/src/cli/cmd/serve.ts:28-30 and packages/opencode/src/cli/cmd/web.ts:89-91) use process.on() for SIGTERM, SIGINT, and SIGHUP handlers.

While process.once() is appropriate for this use case due to the shuttingDown guard preventing duplicate shutdowns, this inconsistency may be confusing. Consider documenting why once() is used here versus on() in other commands, or standardizing the approach across all commands.

Suggested change
process.once("SIGHUP", shutdown)
process.once("SIGTERM", shutdown)
process.once("SIGINT", shutdown)
process.on("SIGHUP", shutdown)
process.on("SIGTERM", shutdown)
process.on("SIGINT", shutdown)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant