


























@@ -1,6 +1,10 @@
11import fsSync from "node:fs";
2-import { describe, expect, it, vi } from "vitest";
3-import { getProcessStartTime, isPidAlive } from "./pid-alive.js";
2+import { afterEach, describe, expect, it, vi } from "vitest";
3+import { getProcessStartTime, isPidAlive, isPidDefinitelyDead } from "./pid-alive.js";
4+5+afterEach(() => {
6+vi.restoreAllMocks();
7+});
4859function mockProcReads(entries: Record<string, string>) {
610const originalReadFileSync = fsSync.readFileSync;
@@ -80,6 +84,60 @@ describe("isPidAlive", () => {
8084});
8185});
828687+describe("isPidDefinitelyDead", () => {
88+it("returns true for invalid PIDs", () => {
89+expect(isPidDefinitelyDead(0)).toBe(true);
90+expect(isPidDefinitelyDead(-1)).toBe(true);
91+expect(isPidDefinitelyDead(1.5)).toBe(true);
92+expect(isPidDefinitelyDead(Number.NaN)).toBe(true);
93+expect(isPidDefinitelyDead(Number.POSITIVE_INFINITY)).toBe(true);
94+});
95+96+it("returns true when process probing reports ESRCH", () => {
97+const error = Object.assign(new Error("missing process"), { code: "ESRCH" });
98+vi.spyOn(process, "kill").mockImplementation(() => {
99+throw error;
100+});
101+102+expect(isPidDefinitelyDead(42)).toBe(true);
103+expect(process.kill).toHaveBeenCalledWith(42, 0);
104+});
105+106+it("returns false when process probing reports EPERM", () => {
107+const error = Object.assign(new Error("permission denied"), { code: "EPERM" });
108+vi.spyOn(process, "kill").mockImplementation(() => {
109+throw error;
110+});
111+112+expect(isPidDefinitelyDead(42)).toBe(false);
113+expect(process.kill).toHaveBeenCalledWith(42, 0);
114+});
115+116+it("returns true for zombie processes on Linux", async () => {
117+const zombiePid = process.pid;
118+vi.spyOn(process, "kill").mockImplementation(() => true);
119+mockProcReads({
120+[`/proc/${zombiePid}/status`]: `Name:\tnode\nUmask:\t0022\nState:\tZ (zombie)\nTgid:\t${zombiePid}\nPid:\t${zombiePid}\n`,
121+});
122+123+await withLinuxProcessPlatform(async () => {
124+expect(isPidDefinitelyDead(zombiePid)).toBe(true);
125+});
126+});
127+128+it("returns false for live non-zombie processes", async () => {
129+const livePid = process.pid;
130+vi.spyOn(process, "kill").mockImplementation(() => true);
131+mockProcReads({
132+[`/proc/${livePid}/status`]: `Name:\tnode\nUmask:\t0022\nState:\tS (sleeping)\nTgid:\t${livePid}\nPid:\t${livePid}\n`,
133+});
134+135+await withLinuxProcessPlatform(async () => {
136+expect(isPidDefinitelyDead(livePid)).toBe(false);
137+});
138+});
139+});
140+83141describe("getProcessStartTime", () => {
84142it("parses linux /proc stat start times and rejects malformed variants", async () => {
85143const fakeStatPrefix = "42 (node) S 1 42 42 0 -1 4194304 12345 0 0 0 100 50 0 0 20 0 8 0 ";
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。