diff --git a/src/main/daemon/terminal-host.ts b/src/main/daemon/terminal-host.ts index d7f0b6609a7..0ed3b0a4615 100644 --- a/src/main/daemon/terminal-host.ts +++ b/src/main/daemon/terminal-host.ts @@ -11,7 +11,7 @@ import { type TerminalSnapshot } from './types' import type { CreateOrAttachOptions, CreateOrAttachResult } from './terminal-host-create-contract' -import { TerminalAgentTeardown } from './terminal-agent-teardown' +import { TerminalSessionTeardown } from './terminal-session-teardown' export type { CreateOrAttachOptions, CreateOrAttachResult } from './terminal-host-create-contract' @@ -46,7 +46,7 @@ export type TerminalHostOptions = { export class TerminalHost { private sessions = new Map() - private agentTeardowns = new TerminalAgentTeardown(this.sessions, (id) => this.reapSession(id)) + private sessionTeardown = new TerminalSessionTeardown(this.sessions, (id) => this.reapSession(id)) private killedTombstones = new Map() private spawnSubprocess: TerminalHostOptions['spawnSubprocess'] private onFinalCheckpoint: TerminalHostOptions['onFinalCheckpoint'] @@ -70,7 +70,7 @@ export class TerminalHost { // Why: async descendant capture must finish before anyone can attach or // dispose/recreate this id. Disposing here would kill the root before the // snapshot and reattaching would hand out a doomed session. - if (this.agentTeardowns.get(opts.sessionId) || existing?.isTerminating) { + if (this.sessionTeardown.get(opts.sessionId) || existing?.isTerminating) { throw new SessionNotFoundError(opts.sessionId) } @@ -202,20 +202,13 @@ export class TerminalHost { } kill(sessionId: string, opts: { immediate?: boolean } = {}): void | Promise { - const pending = this.agentTeardowns.get(sessionId) + const pending = this.sessionTeardown.get(sessionId) if (pending) { - return opts.immediate ? this.agentTeardowns.requestImmediate(sessionId) : pending + return opts.immediate ? this.sessionTeardown.requestImmediate(sessionId) : pending } const session = this.getAliveSession(sessionId) this.recordTombstone(sessionId) - if (session.launchAgent) { - return this.agentTeardowns.kill(sessionId, session, opts.immediate === true) - } - if (opts.immediate) { - this.agentTeardowns.forceImmediate(sessionId, session) - return - } - session.kill() + return this.sessionTeardown.killSession(sessionId, session, opts.immediate === true) } // Why: dispose a dead session's headless emulator and drop it from the map so diff --git a/src/main/daemon/terminal-agent-teardown.ts b/src/main/daemon/terminal-session-teardown.ts similarity index 85% rename from src/main/daemon/terminal-agent-teardown.ts rename to src/main/daemon/terminal-session-teardown.ts index 73bb9c88eb4..0775495677f 100644 --- a/src/main/daemon/terminal-agent-teardown.ts +++ b/src/main/daemon/terminal-session-teardown.ts @@ -8,7 +8,7 @@ type AgentTeardownOperation = { /** Owns agent teardown by session id until descendant capture and root * signalling finish, even when the root exits and its Session is reaped. */ -export class TerminalAgentTeardown { +export class TerminalSessionTeardown { private operations = new Map() constructor( @@ -28,11 +28,22 @@ export class TerminalAgentTeardown { return pending?.promise } - forceImmediate(sessionId: string, session: Session): void { - this.finishImmediate(sessionId, session) + killSession(sessionId: string, session: Session, immediate: boolean): void | Promise { + if (session.launchAgent) { + return this.killAgentSession(sessionId, session, immediate) + } + if (immediate) { + this.finishImmediate(sessionId, session) + } else { + session.kill() + } } - kill(sessionId: string, session: Session, immediate: boolean): void | Promise { + private killAgentSession( + sessionId: string, + session: Session, + immediate: boolean + ): void | Promise { const pending = this.operations.get(sessionId) if (pending) { // Why: an immediate caller is a stronger teardown request and must not