From efb45b51d4d3e9220615b05fb512471380ae74a0 Mon Sep 17 00:00:00 2001 From: "robopipi[bot]" <336283572+robopipi[bot]@users.noreply.github.com> Date: Tue, 3 Nov 2026 22:11:40 +0100 Subject: [PATCH] fix(coding-agent): dispose session runtime after startup benchmark (#11736) With `PI_STARTUP_BENCHMARK=1`, pi initializes interactive mode, stops the TUI, prints the timings and returns. It never disposed the session runtime, so extensions never got `session_shutdown`. If an extension cleans up a timer or a socket in that handler, the resource stays open and the process never exits after printing the timings. This change calls `await runtime.dispose()` right after `interactiveMode.stop()` in the benchmark path. That is the same order a normal interactive quit uses: stop the TUI, then dispose the runtime. No test was added. Nothing in the test suite covers the startup benchmark path, and that path needs a real TTY. Testing: - `npm run check` passes. - I wrote an extension that starts a `setInterval` in `session_start` and clears it in `session_shutdown`. Then I ran `PI_STARTUP_BENCHMARK=1 PI_TIMING=1 pi --offline -ne -e ./ext.ts` in a terminal, wrapped in `timeout --foreground 15`: - before the change: the timings print, then the process hangs until the timeout (exit 124); - after the change: it exits 0. - Without extensions it exits 0 both before and after. Fixes #11693 Requested by @badlogic Co-authored-by: triagent --- packages/coding-agent/src/main.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/coding-agent/src/main.ts b/packages/coding-agent/src/main.ts index 88aa3c5d3..34111cca6 100644 --- a/packages/coding-agent/src/main.ts +++ b/packages/coding-agent/src/main.ts @@ -979,6 +979,7 @@ export async function main(args: string[], options?: MainOptions) { // (Kitty keyboard protocol, device attributes, cell size) before restoring the terminal. await new Promise((resolve) => setTimeout(resolve, 150)); interactiveMode.stop(); + await runtime.dispose(); stopThemeWatcher(); printTimings(); if (process.stdout.writableLength > 0) {