diff --git a/cli/src/__tests__/install-store.test.ts b/cli/src/__tests__/install-store.test.ts index 9e6afb9c899..732ee5267ca 100644 --- a/cli/src/__tests__/install-store.test.ts +++ b/cli/src/__tests__/install-store.test.ts @@ -138,6 +138,15 @@ describe("managed install store", () => { expect(fs.existsSync(paths.lockPath)).toBe(false); }); + it("fails closed without replacing a stale-looking lock", async () => { + const staleToken = "999999:stale"; + await withInstallStoreLock(async () => undefined, paths); + fs.writeFileSync(paths.lockPath, `${staleToken}\n`, { mode: 0o600 }); + + await expect(withInstallStoreLock(async () => undefined, paths)).rejects.toThrow("stale lock"); + expect(fs.readFileSync(paths.lockPath, "utf8")).toBe(`${staleToken}\n`); + }); + it("reports managed provenance only for the payload selected by current", () => { const manifestPayload = payloadPathFor(paths, "npm", "1.0.0"); const currentPayload = payloadPathFor(paths, "npm", "2.0.0"); diff --git a/cli/src/install-store.ts b/cli/src/install-store.ts index 390a414dbc4..d4bb75cb657 100644 --- a/cli/src/install-store.ts +++ b/cli/src/install-store.ts @@ -144,15 +144,6 @@ export function assertManagedInstallStore(paths = resolveInstallStorePaths()): I return manifest; } -function processIsAlive(pid: number): boolean { - try { - process.kill(pid, 0); - return true; - } catch (error) { - return (error as NodeJS.ErrnoException).code === "EPERM"; - } -} - export async function withInstallStoreLock( callback: () => Promise, paths = resolveInstallStorePaths(), @@ -172,18 +163,11 @@ export async function withInstallStoreLock( } const owner = fs.readFileSync(paths.lockPath, "utf8").trim(); const ownerPid = Number.parseInt(owner.split(":", 1)[0] ?? "", 10); - if (Number.isInteger(ownerPid) && ownerPid > 0 && processIsAlive(ownerPid)) { - throw new Error(`Another managed install is already running (pid ${ownerPid}).`); - } - fs.rmSync(paths.lockPath, { force: true }); - try { - fs.linkSync(temporaryPath, paths.lockPath); - } catch (retryError) { - if ((retryError as NodeJS.ErrnoException).code === "EEXIST") { - throw new Error("Another managed install started while recovering a stale lock."); - } - throw retryError; - } + const ownerLabel = Number.isInteger(ownerPid) && ownerPid > 0 ? ` (pid ${ownerPid})` : ""; + throw new Error( + `Another managed install is already running${ownerLabel}. ` + + `If no install process is active, remove the stale lock at ${paths.lockPath} and retry.`, + ); } finally { fs.rmSync(temporaryPath, { force: true }); }