Skip to content

Commit 124e2b4

Browse files
committed
test(cli): check whether Chrome outlives a killed parent on each OS
1 parent f9fa6ac commit 124e2b4

2 files changed

Lines changed: 50 additions & 3 deletions

File tree

‎.github/checkfast/pipekill.mjs‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Does a Chrome launched by a node parent survive SIGKILL of that parent? pipe-only vs pipe+port, 3 trials each.
2+
import { spawn } from "node:child_process";
3+
import { mkdtempSync } from "node:fs";
4+
import { tmpdir } from "node:os";
5+
import { join } from "node:path";
6+
import { createRequire } from "node:module";
7+
8+
const chrome = process.argv[2];
9+
if (process.argv[3] === "child") {
10+
const puppeteer = createRequire(join(process.cwd(), "packages/cli/package.json"))("puppeteer-core");
11+
const args = process.argv[4] === "port" ? ["--remote-debugging-port=0"] : [];
12+
const b = await puppeteer.launch({ executablePath: chrome, pipe: true, headless: true,
13+
userDataDir: mkdtempSync(join(tmpdir(), "cf-pipekill-")), args });
14+
const p = await b.newPage();
15+
await p.goto("about:blank");
16+
console.log(`PID ${b.process().pid}`);
17+
setInterval(() => {}, 1000);
18+
} else {
19+
const alive = (pid) => { try { process.kill(pid, 0); return true; } catch { return false; } };
20+
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
21+
let failures = 0;
22+
for (const mode of ["pipe", "port"]) {
23+
for (let t = 1; t <= 3; t++) {
24+
const child = spawn(process.execPath, [process.argv[1], chrome, "child", mode], { stdio: ["ignore", "pipe", "inherit"] });
25+
const pid = await new Promise((resolve) => {
26+
let out = "";
27+
child.stdout.on("data", (d) => { out += d; const m = out.match(/PID (\d+)/); if (m) resolve(Number(m[1])); });
28+
});
29+
child.kill("SIGKILL");
30+
await wait(3000);
31+
const survived = alive(pid);
32+
console.log(`${process.platform} ${mode} trial${t} chrome ${pid} ${survived ? "ALIVE" : "exited"}`);
33+
if (survived) {
34+
if (mode === "pipe") failures++;
35+
if (process.platform === "win32") spawn("taskkill", ["/PID", String(pid), "/T", "/F"]);
36+
else process.kill(pid, "SIGKILL");
37+
await wait(1000);
38+
}
39+
}
40+
}
41+
process.exit(failures ? 1 : 0);
42+
}

‎.github/workflows/checkfast-timing.yml‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
matrix:
1515
include:
1616
- { os: windows-latest, defender: on }
17-
- { os: windows-latest, defender: off }
17+
- { os: macos-latest, defender: none }
1818
- { os: ubuntu-latest, defender: none }
1919
env:
2020
HYPERFRAMES_NO_TELEMETRY: "1"
@@ -34,6 +34,9 @@ jobs:
3434
- name: Install FFmpeg (Linux)
3535
if: runner.os == 'Linux'
3636
run: sudo apt-get update -qq && sudo apt-get install -y -qq ffmpeg
37+
- name: Install FFmpeg (macOS)
38+
if: runner.os == 'macOS'
39+
run: brew install ffmpeg
3740
- name: Set FFMPEG_BIN for bun install
3841
if: runner.os == 'Windows'
3942
shell: pwsh
@@ -56,9 +59,11 @@ jobs:
5659
bun run --filter @hyperframes/core build
5760
bun run --filter '@hyperframes/{engine,producer,player,studio}' build
5861
bun run --filter @hyperframes/cli build
59-
- name: Time check
62+
- name: Chrome survives a killed parent?
6063
shell: bash
61-
run: bash .github/checkfast/run.sh
64+
run: |
65+
node packages/cli/bin/hyperframes.mjs browser ensure > /dev/null 2>&1
66+
node .github/checkfast/pipekill.mjs "$(node packages/cli/bin/hyperframes.mjs browser path)"
6267
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
6368
if: always()
6469
with:

0 commit comments

Comments
 (0)