diff --git a/src/cliproxy/auth/oauth-process.ts b/src/cliproxy/auth/oauth-process.ts index 344e156b..ba157784 100644 --- a/src/cliproxy/auth/oauth-process.ts +++ b/src/cliproxy/auth/oauth-process.ts @@ -6,20 +6,8 @@ */ import { spawn, ChildProcess } from 'child_process'; - -/** - * Kill process with SIGTERM, escalating to SIGKILL if it doesn't exit - */ -function killWithEscalation(proc: ChildProcess, gracePeriodMs = 3000): void { - proc.kill('SIGTERM'); - const timer = setTimeout(() => { - if (proc.exitCode === null) { - proc.kill('SIGKILL'); - } - }, gracePeriodMs); - proc.once('exit', () => clearTimeout(timer)); -} import { ok, fail, info, warn } from '../../utils/ui'; +import { killWithEscalation } from '../../utils/process-utils'; import { tryKiroImport } from './kiro-import'; import { CLIProxyProvider } from '../types'; import { AccountInfo } from '../account-manager'; @@ -371,9 +359,9 @@ export function executeOAuthProcess(options: OAuthProcessOptions): Promise { - if (cancelledSessionId === state.sessionId && authProcess && !authProcess.killed) { + if (cancelledSessionId === state.sessionId && authProcess && authProcess.exitCode === null) { log('Session cancelled externally'); - authProcess.kill('SIGTERM'); + killWithEscalation(authProcess); } }; authSessionEvents.on('session:cancelled', handleCancel); diff --git a/src/delegation/headless-executor.ts b/src/delegation/headless-executor.ts index 3f803c03..977b5ff7 100644 --- a/src/delegation/headless-executor.ts +++ b/src/delegation/headless-executor.ts @@ -5,21 +5,9 @@ * Spawns claude with -p flag for single-turn execution */ -import { spawn, ChildProcess } from 'child_process'; - -/** - * Kill process with SIGTERM, escalating to SIGKILL if it doesn't exit - */ -function killWithEscalation(proc: ChildProcess, gracePeriodMs = 3000): void { - proc.kill('SIGTERM'); - const timer = setTimeout(() => { - if (proc.exitCode === null) { - proc.kill('SIGKILL'); - } - }, gracePeriodMs); - proc.once('exit', () => clearTimeout(timer)); -} +import { spawn } from 'child_process'; import * as path from 'path'; +import { killWithEscalation } from '../utils/process-utils'; import * as fs from 'fs'; import { SessionManager } from './session-manager'; import { SettingsParser } from './settings-parser'; diff --git a/src/utils/process-utils.ts b/src/utils/process-utils.ts new file mode 100644 index 00000000..ac22f8ba --- /dev/null +++ b/src/utils/process-utils.ts @@ -0,0 +1,20 @@ +/** + * Process management utilities + */ + +import { ChildProcess } from 'child_process'; + +/** + * Kill process with SIGTERM, escalating to SIGKILL if it doesn't exit. + * Uses exitCode === null (not proc.killed) to check if process is still running, + * since proc.killed only indicates a signal was sent, not that the process exited. + */ +export function killWithEscalation(proc: ChildProcess, gracePeriodMs = 3000): void { + proc.kill('SIGTERM'); + const timer = setTimeout(() => { + if (proc.exitCode === null) { + proc.kill('SIGKILL'); + } + }, gracePeriodMs); + proc.once('exit', () => clearTimeout(timer)); +}