@ai-ecoverse/slicc-shared-web 1.10.2 → 1.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/harness/chrome.mjs +20 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -99,8 +99,8 @@ Why it works the way it does:
|
|
|
99
99
|
## Cleanup
|
|
100
100
|
|
|
101
101
|
`close()` stops Chrome and removes its profile. It asks Chrome to close, waits up to 10 s for the exit, sends `SIGKILL`, waits up to 5 s more and then moves on with a warning, so a browser that ignores `Browser.close` or a missed exit never hangs teardown. A test process that ends without `close()` still leaves nothing running:
|
|
102
|
-
- on `exit` and on `SIGINT`, `SIGTERM` or `SIGHUP`, the harness kills every browser it started in that process with `SIGKILL` and removes its profile and crash dump directory, then re-raises the signal so the process ends the way it would have;
|
|
103
|
-
- when the test process dies of `SIGKILL`, no handler runs. A watchdog, a `sh` that reads a pipe from the test process, then gets end of file and kills Chrome with `SIGKILL` at once. Chrome also shuts itself down when the CDP pipe closes, but that can take seconds. Only the profile stays behind;
|
|
102
|
+
- on `exit` and on `SIGINT`, `SIGTERM` or `SIGHUP`, the harness kills every browser it started in that process, with all its helper processes (Chrome runs in its own process group), with `SIGKILL` and removes its profile and crash dump directory, then re-raises the signal so the process ends the way it would have;
|
|
103
|
+
- when the test process dies of `SIGKILL`, no handler runs. A watchdog, a `sh` in its own process group that reads a pipe from the test process, then gets end of file and kills Chrome's process group with `SIGKILL` at once. Chrome also shuts itself down when the CDP pipe closes, but that can take seconds. Only the profile stays behind;
|
|
104
104
|
- the first `launch()` in a process removes every `slicc-harness-*` directory in `$TMPDIR` that is older than a day, or older than a minute and no running process uses as its `--user-data-dir`. It never kills a process.
|
|
105
105
|
|
|
106
106
|
## Crash dumps
|
package/harness/chrome.mjs
CHANGED
|
@@ -74,6 +74,7 @@ export async function start(
|
|
|
74
74
|
) {
|
|
75
75
|
const child = spawn(executable, args, {
|
|
76
76
|
env,
|
|
77
|
+
detached: true,
|
|
77
78
|
stdio: ['ignore', 'ignore', 'pipe', 'pipe', 'pipe'],
|
|
78
79
|
});
|
|
79
80
|
const stderr = lines(child.stderr);
|
|
@@ -111,7 +112,7 @@ export async function stop(cdp, child, waits = WAITS) {
|
|
|
111
112
|
await bounded(cdp.send('Browser.close').catch(ignore), 'Browser.close', waits.close);
|
|
112
113
|
cdp.close();
|
|
113
114
|
if (gone() || (await bounded(exited, 'exit', waits.exit)) !== TIMED_OUT || gone()) return;
|
|
114
|
-
|
|
115
|
+
kill(child);
|
|
115
116
|
if (gone() || (await bounded(exited, 'exit after SIGKILL', waits.kill)) !== TIMED_OUT) return;
|
|
116
117
|
if (!gone()) console.warn(`chrome: pid ${child.pid} still runs after SIGKILL, moving on`);
|
|
117
118
|
}
|
|
@@ -123,15 +124,27 @@ export const GRACE = 60 * 1000;
|
|
|
123
124
|
const signals = ['SIGINT', 'SIGTERM', 'SIGHUP'];
|
|
124
125
|
const running = new Set();
|
|
125
126
|
|
|
126
|
-
function kill(child) {
|
|
127
|
+
export function kill(child) {
|
|
128
|
+
if (child.pid > 0 && child.spawnargs?.length) {
|
|
129
|
+
try {
|
|
130
|
+
process.kill(-child.pid, 'SIGKILL');
|
|
131
|
+
} catch {}
|
|
132
|
+
}
|
|
127
133
|
if (child.exitCode === null && child.signalCode === null) child.kill('SIGKILL');
|
|
128
134
|
}
|
|
129
135
|
|
|
130
|
-
function
|
|
131
|
-
for (const {
|
|
132
|
-
for (const child of children) kill(child);
|
|
136
|
+
function remove(entries) {
|
|
137
|
+
for (const { paths } of entries) {
|
|
133
138
|
for (const path of paths) rmSync(path, { recursive: true, force: true });
|
|
134
139
|
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function reap() {
|
|
143
|
+
const entries = [...running];
|
|
144
|
+
for (const { children } of entries) children.forEach(kill);
|
|
145
|
+
remove(entries);
|
|
146
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 200);
|
|
147
|
+
remove(entries);
|
|
135
148
|
running.clear();
|
|
136
149
|
unhook();
|
|
137
150
|
}
|
|
@@ -152,7 +165,8 @@ function unhook() {
|
|
|
152
165
|
}
|
|
153
166
|
|
|
154
167
|
export function watchdog(pid) {
|
|
155
|
-
const dog = spawn('sh', ['-c', 'read -r _; kill -9 "$0" 2>/dev/null', String(pid)], {
|
|
168
|
+
const dog = spawn('sh', ['-c', 'read -r _; kill -9 -"$0" "$0" 2>/dev/null', String(pid)], {
|
|
169
|
+
detached: true,
|
|
156
170
|
stdio: ['pipe', 'ignore', 'ignore'],
|
|
157
171
|
});
|
|
158
172
|
dog.on('error', ignore);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/slicc-shared-web",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.3",
|
|
4
4
|
"description": "Shared Renovate, Biome, TypeScript, lefthook and GitHub Actions configuration, plus the CDP integration-test harness, for SLICC's web repos",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|