From a7947f1fac3e02a52df4756116ea0577ee8d82a2 Mon Sep 17 00:00:00 2001 From: "paseo-bot[bot]" <266920839+paseo-bot[bot]@users.noreply.github.com> Date: Sun, 18 Oct 2026 13:36:22 +0200 Subject: [PATCH] test(server): reproduce shared daemon lock loss across PID namespaces Retain acquisition and stop regressions for #4307. These tests intentionally fail on main; they do not choose a namespace ownership or crash-recovery policy. Co-authored-by: Cong Xu <3174585+xu-c@users.noreply.github.com> --- .../src/server/pid-lock-namespace.test.ts | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 packages/server/src/server/pid-lock-namespace.test.ts diff --git a/packages/server/src/server/pid-lock-namespace.test.ts b/packages/server/src/server/pid-lock-namespace.test.ts new file mode 100644 index 0000000000..9c7224998e --- /dev/null +++ b/packages/server/src/server/pid-lock-namespace.test.ts @@ -0,0 +1,43 @@ +import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { expect, test } from "vitest"; +import { stopDaemonInstance } from "./daemon-instance.js"; +import { acquirePidLock } from "./pid-lock.js"; + +// A shared home exposes a live supervisor's lock to a PID namespace in which its PID +// does not exist. The Docker reproduction in #4307 establishes that condition; these +// filesystem tests retain it without requiring a container runtime in the unit suite. +async function withUnseenOwner(run: (home: string, contents: string) => Promise) { + const home = await mkdtemp(join(tmpdir(), "paseo-unseen-owner-")); + const contents = JSON.stringify({ + pid: 2_147_483_647, + startedAt: new Date().toISOString(), + hostname: "shared-host", + uid: process.getuid?.() ?? 0, + listen: null, + heartbeat: true, + }); + try { + await writeFile(join(home, "paseo.pid"), contents); + await run(home, contents); + } finally { + await rm(home, { recursive: true, force: true }); + } +} + +test("acquiring a lock preserves a fresh heartbeat from an unseen owner", async () => { + await withUnseenOwner(async (home, contents) => { + await expect(acquirePidLock(home, null)).rejects.toThrow(); + expect(await readFile(join(home, "paseo.pid"), "utf8")).toBe(contents); + }); +}); + +test("stopping an unseen owner preserves its fresh shared lock", async () => { + await withUnseenOwner(async (home, contents) => { + // Either refusing the operation or returning without modifying the foreign lock is safe. + // The failure being locked down is deleting the live supervisor's lock. + await stopDaemonInstance(home).catch(() => undefined); + expect(await readFile(join(home, "paseo.pid"), "utf8")).toBe(contents); + }); +});