fix(coding-agent): fire session shutdown on TERM and HUP closes #3212

This commit is contained in:
Mario Zechner
2026-04-15 16:36:30 +02:00
parent 3a13fa80c8
commit 5d440b055c
6 changed files with 92 additions and 7 deletions

View File

@@ -212,6 +212,7 @@ export class InteractiveMode {
// Agent subscription unsubscribe function
private unsubscribe?: () => void;
private signalCleanupHandlers: Array<() => void> = [];
// Track if editor is in bash mode (text starts with !)
private isBashMode = false;
@@ -477,6 +478,8 @@ export class InteractiveMode {
async init(): Promise<void> {
if (this.isInitialized) return;
this.registerSignalHandlers();
// Load changelog (only show new entries, skip for resumed sessions)
this.changelogMarkdown = this.getChangelogForDisplay();
@@ -2905,6 +2908,7 @@ export class InteractiveMode {
private async shutdown(): Promise<void> {
if (this.isShuttingDown) return;
this.isShuttingDown = true;
this.unregisterSignalHandlers();
await this.runtimeHost.dispose();
// Wait for any pending renders to complete
@@ -2927,6 +2931,30 @@ export class InteractiveMode {
await this.shutdown();
}
private registerSignalHandlers(): void {
this.unregisterSignalHandlers();
const signals: NodeJS.Signals[] = ["SIGTERM"];
if (process.platform !== "win32") {
signals.push("SIGHUP");
}
for (const signal of signals) {
const handler = () => {
void this.shutdown();
};
process.on(signal, handler);
this.signalCleanupHandlers.push(() => process.off(signal, handler));
}
}
private unregisterSignalHandlers(): void {
for (const cleanup of this.signalCleanupHandlers) {
cleanup();
}
this.signalCleanupHandlers = [];
}
private handleCtrlZ(): void {
// Keep the event loop alive while suspended. Without this, stopping the TUI
// can leave Node with no ref'ed handles, causing the process to exit on fg
@@ -4785,6 +4813,7 @@ export class InteractiveMode {
}
stop(): void {
this.unregisterSignalHandlers();
if (this.loadingAnimation) {
this.loadingAnimation.stop();
this.loadingAnimation = undefined;