42 lines
1.7 KiB
TypeScript
42 lines
1.7 KiB
TypeScript
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import path from "node:path";
|
|
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
import { runProviderProcess } from "../../../scripts/lib/provider-process-runner.ts";
|
|
|
|
describe("CI-runner provider process-group lifecycle", () => {
|
|
it("kills and reaps a stubborn provider process group including its descendant", async () => {
|
|
const root = await mkdtemp(path.join(tmpdir(), "provider-process-group-"));
|
|
const descendantPidPath = path.join(root, "descendant.pid");
|
|
try {
|
|
const source = [
|
|
"const { spawn } = require('node:child_process');",
|
|
"const { writeFileSync } = require('node:fs');",
|
|
"const child = spawn(process.execPath, ['-e', `process.on('SIGTERM', () => {}); setInterval(() => {}, 1000)`], { stdio: 'ignore' });",
|
|
"writeFileSync(process.env.DESCENDANT_PID_PATH, String(child.pid));",
|
|
"process.on('SIGTERM', () => {});",
|
|
"setInterval(() => {}, 1000);",
|
|
].join("\n");
|
|
|
|
const running = runProviderProcess({
|
|
executable: process.execPath,
|
|
arguments: ["-e", source],
|
|
environment: {
|
|
PATH: process.env.PATH,
|
|
DESCENDANT_PID_PATH: descendantPidPath,
|
|
},
|
|
timeoutMs: 250,
|
|
});
|
|
|
|
await expect(running).rejects.toThrow(/timed out.*process close/u);
|
|
const descendantPid = Number(await readFile(descendantPidPath, "utf8"));
|
|
expect(Number.isSafeInteger(descendantPid) && descendantPid > 0).toBe(true);
|
|
expect(() => process.kill(descendantPid, 0)).toThrow(/ESRCH|no such process/u);
|
|
} finally {
|
|
await rm(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
});
|