fix: replace domain-specific exit handler with generic signal handler registry (#299)

* fix: replace domain-specific exit handler with generic signal handler registry

Rewrite exitHandler.ts as a generic, domain-agnostic exit signal module
that exports onExitSignal(handler) returning a dispose function.

- subprocess.ts now registers via onExitSignal instead of direct
  process.on(SIGINT/SIGTERM) calls
- resolveTokens registers a signal handler that captures tokens by
  closure, fixing the race condition where the exit handler would
  read the wrong token after disposal
- Remove setupExitHandler and runCleanup — domain cleanup is handled
  by post.ts + await using

Co-authored-by: Cursor <cursoragent@cursor.com>

* tweaks

* simplify handler installation

* extract to util

* fix race in dispose

* wrap dispose body in try/finally to ensure disposingRef always settles

---------

Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
This commit is contained in:
pullfrog[bot]
2026-02-20 10:23:56 +00:00
committed by pullfrog[bot]
parent 70f1c47a28
commit ee100354da
10 changed files with 198 additions and 317 deletions
+1 -6
View File
@@ -12,7 +12,6 @@ import { validateAgentApiKey } from "./utils/apiKeys.ts";
import { resolveBody } from "./utils/body.ts";
import { log, writeSummary } from "./utils/cli.ts";
import { reportErrorToComment } from "./utils/errorReport.ts";
import { setupExitHandler } from "./utils/exitHandler.ts";
import { resolveGit } from "./utils/gitAuth.ts";
import { createOctokit } from "./utils/github.ts";
import { resolveInstructions } from "./utils/instructions.ts";
@@ -52,8 +51,6 @@ export async function main(): Promise<MainResult> {
typeof resolvedPromptInput !== "string" ? resolvedPromptInput.progressCommentId : undefined,
});
setupExitHandler(toolState);
// resolve and fingerprint git binary before any agent code runs
resolveGit();
@@ -247,8 +244,6 @@ export async function main(): Promise<MainResult> {
error: errorMessage,
};
} finally {
if (activityTimeout) {
activityTimeout.stop();
}
activityTimeout?.stop();
}
}