From a7b3809a128e2ad4eed36344d68beb8d64e6897c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=8B=E7=93=9C=E4=B8=80=E5=8D=81=E9=9B=AA?= Date: Sat, 9 May 2026 19:38:52 +0800 Subject: [PATCH] Only track hook states for running PIDs Stop exposing and retaining hook state for PIDs that are not currently running. listProcesses() no longer returns orphaned states; live-pipe handling ignores PIDs not present in the current process list. When a process is not running its state is immediately torn down (tearDownClient called) and removed, and bridgeManager.onPidDisconnected is notified if the state was logged in. Also reorganized runningSet creation so it can be reused for these checks. --- packages/core/src/hook/hook-manager.ts | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/core/src/hook/hook-manager.ts b/packages/core/src/hook/hook-manager.ts index 808a3b23..0933babb 100644 --- a/packages/core/src/hook/hook-manager.ts +++ b/packages/core/src/hook/hook-manager.ts @@ -76,9 +76,7 @@ export class HookManager { async listProcesses(): Promise { const processes = listHookProcesses(); - const seen = new Set(); for (const proc of processes) { - seen.add(proc.pid); const state = this.ensureState(proc.pid); state.name = proc.name || state.name; state.path = proc.path || state.path; @@ -87,11 +85,6 @@ export class HookManager { for (const proc of processes) { result.push(this.toPublicInfo(this.ensureState(proc.pid))); } - for (const state of this.states.values()) { - if (!seen.has(state.pid) && (state.injected || state.client)) { - result.push(this.toPublicInfo(state)); - } - } return result.sort((a, b) => a.pid - b.pid); } @@ -316,6 +309,7 @@ export class HookManager { try { const livePipes = await QqHookClient.listLivePipes(); const processes = listHookProcesses(); + const runningSet = new Set(processes.map(p => p.pid)); // Refresh metadata + ensure a state entry exists for each known PID. for (const proc of processes) { @@ -325,6 +319,7 @@ export class HookManager { } // Auto-detect hooks that survived a SnowLuma restart or failed unload. for (const pid of livePipes) { + if (!runningSet.has(pid)) continue; const state = this.ensureState(pid); if (!state.injected) { state.injected = true; @@ -334,14 +329,15 @@ export class HookManager { } } - const runningSet = new Set(processes.map(p => p.pid)); const tasks: Promise[] = []; for (const state of [...this.states.values()]) { const alivePipe = livePipes.has(state.pid); const aliveProc = runningSet.has(state.pid); - // Reap stale state entries that have nothing left to do. - if (!aliveProc && !alivePipe && !state.injected && !state.client) { + if (!aliveProc) { + const wasLoggedIn = state.loggedIn; + this.tearDownClient(state); + if (wasLoggedIn) this.bridgeManager.onPidDisconnected(state.pid); this.states.delete(state.pid); continue; }