mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-13 00:19:03 +02:00
test(browse): unit coverage for the close() SIGKILL fallback
The wedge fix (capture the Chromium child before the close race, SIGKILL on timeout) shipped without a test of the branch it added — the coverage audit flagged it as the diff's one regression-gap. The 5s race window becomes an injectable closeRaceMs field, and four unit tests pin: SIGKILL on hang, no SIGKILL on clean close, no SIGKILL on an already-exited child, SIGKILL on a rejecting close.
This commit is contained in:
@@ -797,6 +797,12 @@ export class BrowserManager {
|
||||
this.consecutiveFailures = 0;
|
||||
}
|
||||
|
||||
// How long close() waits for a graceful shutdown before falling back to
|
||||
// SIGKILL (launched mode) or abandoning the context close (headed mode).
|
||||
// A field, not a literal, so the SIGKILL fallback is unit-testable without
|
||||
// a 5-second wait.
|
||||
private closeRaceMs = 5000;
|
||||
|
||||
async close() {
|
||||
// unref'd race timer: without unref, every successful close still pins
|
||||
// the caller's event loop for the full window.
|
||||
@@ -811,7 +817,7 @@ export class BrowserManager {
|
||||
if (this.browser) this.browser.removeAllListeners('disconnected');
|
||||
await Promise.race([
|
||||
this.context ? this.context.close() : Promise.resolve(),
|
||||
raceTimeout(5000),
|
||||
raceTimeout(this.closeRaceMs),
|
||||
]).catch(() => {});
|
||||
} else {
|
||||
// Launched mode: close the browser we spawned.
|
||||
@@ -824,7 +830,7 @@ export class BrowserManager {
|
||||
const child = this.browser.process?.();
|
||||
const closed = await Promise.race([
|
||||
this.browser.close().then(() => true as const),
|
||||
raceTimeout(5000),
|
||||
raceTimeout(this.closeRaceMs),
|
||||
]).catch(() => false as const);
|
||||
if (closed === false && child && child.exitCode === null && !child.killed) {
|
||||
try { child.kill('SIGKILL'); } catch { /* already gone */ }
|
||||
|
||||
Reference in New Issue
Block a user