fix(#2822): properly cleanup tmux sessions on process shutdown
Two issues fixed: 1. process-cleanup.ts used fire-and-forget void Promise for shutdown handlers — now properly collects and awaits all cleanup promises via Promise.allSettled, with dedup guard to prevent double cleanup 2. TmuxSessionManager was never registered for process cleanup — now registered in create-managers.ts via registerManagerForCleanup Also fixed setTimeout().unref() which could let the process exit before cleanup completes.
This commit is contained in:
@@ -7,6 +7,7 @@ import { BackgroundManager } from "./features/background-agent"
|
||||
import { SkillMcpManager } from "./features/skill-mcp-manager"
|
||||
import { initTaskToastManager } from "./features/task-toast-manager"
|
||||
import { TmuxSessionManager } from "./features/tmux-subagent"
|
||||
import { registerManagerForCleanup } from "./features/background-agent/process-cleanup"
|
||||
import { createConfigHandler } from "./plugin-handlers"
|
||||
import { log } from "./shared"
|
||||
import { markServerRunningInProcess } from "./shared/tmux/tmux-utils/server-health"
|
||||
@@ -30,6 +31,14 @@ export function createManagers(args: {
|
||||
markServerRunningInProcess()
|
||||
const tmuxSessionManager = new TmuxSessionManager(ctx, tmuxConfig)
|
||||
|
||||
registerManagerForCleanup({
|
||||
shutdown: async () => {
|
||||
await tmuxSessionManager.cleanup().catch((error) => {
|
||||
log("[create-managers] tmux cleanup error during process shutdown:", error)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
const backgroundManager = new BackgroundManager(
|
||||
ctx,
|
||||
pluginConfig.background_task,
|
||||
|
||||
@@ -11,7 +11,7 @@ function registerProcessSignal(
|
||||
handler()
|
||||
if (exitAfter) {
|
||||
process.exitCode = 0
|
||||
setTimeout(() => process.exit(), 6000).unref()
|
||||
setTimeout(() => process.exit(), 6000)
|
||||
}
|
||||
}
|
||||
process.on(signal, listener)
|
||||
@@ -32,16 +32,26 @@ export function registerManagerForCleanup(manager: CleanupTarget): void {
|
||||
if (cleanupRegistered) return
|
||||
cleanupRegistered = true
|
||||
|
||||
let cleanupPromise: Promise<void> | undefined
|
||||
|
||||
const cleanupAll = () => {
|
||||
if (cleanupPromise) return
|
||||
const promises: Promise<void>[] = []
|
||||
for (const m of cleanupManagers) {
|
||||
try {
|
||||
void Promise.resolve(m.shutdown()).catch((error) => {
|
||||
log("[background-agent] Error during async shutdown cleanup:", error)
|
||||
})
|
||||
promises.push(
|
||||
Promise.resolve(m.shutdown()).catch((error) => {
|
||||
log("[background-agent] Error during async shutdown cleanup:", error)
|
||||
})
|
||||
)
|
||||
} catch (error) {
|
||||
log("[background-agent] Error during shutdown cleanup:", error)
|
||||
}
|
||||
}
|
||||
cleanupPromise = Promise.allSettled(promises).then(() => {})
|
||||
cleanupPromise.then(() => {
|
||||
log("[background-agent] All shutdown cleanup completed")
|
||||
})
|
||||
}
|
||||
|
||||
const registerSignal = (signal: ProcessCleanupEvent, exitAfter: boolean): void => {
|
||||
|
||||
Reference in New Issue
Block a user