diff --git a/src/daemon/launchd.test.ts b/src/daemon/launchd.test.ts index 1a4819b9c1d..887aed55b98 100644 --- a/src/daemon/launchd.test.ts +++ b/src/daemon/launchd.test.ts @@ -554,6 +554,23 @@ describe("launchd install", () => { expect(output).toContain("did not fully stop the service"); }); + it("treats launchctl print state=running as running even when pid is missing", async () => { + const env = createDefaultLaunchdEnv(); + const stdout = new PassThrough(); + let output = ""; + state.stopLeavesRunning = true; + state.printOutput = "state = running\n"; + stdout.on("data", (chunk: Buffer) => { + output += chunk.toString(); + }); + + await stopLaunchAgent({ env, stdout }); + + expect(state.launchctlCalls.some((call) => call[0] === "bootout")).toBe(true); + expect(output).toContain("Stopped LaunchAgent (degraded)"); + expect(output).toContain("did not fully stop the service"); + }); + it("falls back to bootout when launchctl stop itself errors", async () => { const env = createDefaultLaunchdEnv(); const stdout = new PassThrough(); diff --git a/src/daemon/launchd.ts b/src/daemon/launchd.ts index a99f4a6c449..917525f46cf 100644 --- a/src/daemon/launchd.ts +++ b/src/daemon/launchd.ts @@ -519,7 +519,10 @@ async function probeLaunchAgentState(serviceTarget: string): Promise 1) { + if ( + normalizeLowercaseStringOrEmpty(runtime.state) === "running" || + (typeof runtime.pid === "number" && runtime.pid > 1) + ) { return { state: "running" }; } return { state: "stopped" };