@feigi/fleet-ctl 3.102.3 → 3.102.4
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/package.json +1 -1
- package/scripts/recipe-check.mjs +43 -24
package/package.json
CHANGED
package/scripts/recipe-check.mjs
CHANGED
|
@@ -64,14 +64,17 @@
|
|
|
64
64
|
// forwarded to the running command, no further command starts, and nothing
|
|
65
65
|
// is written, so an older record stays where it is — settle compares the
|
|
66
66
|
// record's tree with the reported head's tree, so a stale one cannot pass for
|
|
67
|
-
// this run.
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
// its
|
|
72
|
-
//
|
|
73
|
-
//
|
|
74
|
-
//
|
|
67
|
+
// this run. Each command runs in a process group of its own, and the forwarded
|
|
68
|
+
// signal is delivered to that whole group — the `sh -c`, the commands it
|
|
69
|
+
// started and everything they started — so a compound command stops with it,
|
|
70
|
+
// unless a member of the group ignores the signal, and this script exits once
|
|
71
|
+
// the run closes its output. A SIGKILL aimed at this script, by pid or at its
|
|
72
|
+
// process group, cannot be forwarded and leaves the command's group running.
|
|
73
|
+
// A signal received before step 3 takes its default action: the script dies
|
|
74
|
+
// of it, printing nothing. A command that dies of a signal this script did
|
|
75
|
+
// not receive is a failure like any other, recorded red as the signal's
|
|
76
|
+
// number plus 128. A record is a claim, no attestation: the member produces
|
|
77
|
+
// it, and nothing here stops a forged one.
|
|
75
78
|
//
|
|
76
79
|
// Exit status: 0 both commands passed and the record is written; 1 a command
|
|
77
80
|
// failed — the record says which, and the script's stderr names it; 2 a
|
|
@@ -208,16 +211,16 @@ async function cli() {
|
|
|
208
211
|
});
|
|
209
212
|
}
|
|
210
213
|
// A SIGTERM, SIGINT or SIGHUP this script itself receives is forwarded to
|
|
211
|
-
// the running command and marks the run killed: no further
|
|
212
|
-
// and nothing is recorded. That holds until the record is
|
|
213
|
-
// signal during the commands never takes the default action
|
|
214
|
-
// the output still queued. After that only queued output is
|
|
215
|
-
// signal takes its default action: the handler removes every
|
|
216
|
-
// re-raises it, so a reader that stalls on that output cannot
|
|
217
|
-
// process no signal stops. The handlers are never removed eagerly
|
|
218
|
-
// decision: removing them drops a signal caught but not yet
|
|
219
|
-
// one landing between the record's rename and that removal —
|
|
220
|
-
// leave the process running with nothing left to stop it.
|
|
214
|
+
// the running command's process group and marks the run killed: no further
|
|
215
|
+
// command starts and nothing is recorded. That holds until the record is
|
|
216
|
+
// decided, so a signal during the commands never takes the default action
|
|
217
|
+
// and cuts off the output still queued. After that only queued output is
|
|
218
|
+
// left, and a signal takes its default action: the handler removes every
|
|
219
|
+
// handler and re-raises it, so a reader that stalls on that output cannot
|
|
220
|
+
// leave a process no signal stops. The handlers are never removed eagerly
|
|
221
|
+
// at the decision: removing them drops a signal caught but not yet
|
|
222
|
+
// dispatched — one landing between the record's rename and that removal —
|
|
223
|
+
// which would leave the process running with nothing left to stop it.
|
|
221
224
|
const run = { killed: null, child: null, ranMs: 0, decided: false };
|
|
222
225
|
const handlers = KILL_SIGNALS.map((sig) => [sig, () => {
|
|
223
226
|
if (run.decided) {
|
|
@@ -226,7 +229,7 @@ async function cli() {
|
|
|
226
229
|
return;
|
|
227
230
|
}
|
|
228
231
|
run.killed ??= sig;
|
|
229
|
-
run.child
|
|
232
|
+
signalGroup(run.child, sig);
|
|
230
233
|
}]);
|
|
231
234
|
for (const [sig, handler] of handlers) process.on(sig, handler);
|
|
232
235
|
const check = checkCmd.trim() === "true"
|
|
@@ -278,17 +281,33 @@ async function cli() {
|
|
|
278
281
|
|
|
279
282
|
if (isCLI(import.meta.url)) await cli();
|
|
280
283
|
|
|
281
|
-
//
|
|
282
|
-
//
|
|
283
|
-
//
|
|
284
|
-
//
|
|
284
|
+
// The signal goes to the command's whole process group. A group that is
|
|
285
|
+
// already gone has nothing to receive it, so ESRCH is not an error. EPERM is
|
|
286
|
+
// macOS's answer for a group whose members have all exited but are not yet
|
|
287
|
+
// reaped, and for one holding a member this user may not signal: the
|
|
288
|
+
// command's own shell is then signalled directly. Any other failure still
|
|
289
|
+
// surfaces. A spawn that never produced a pid has no group.
|
|
290
|
+
function signalGroup(child, sig) {
|
|
291
|
+
if (child?.pid === undefined) return;
|
|
292
|
+
try {
|
|
293
|
+
process.kill(-child.pid, sig);
|
|
294
|
+
} catch (e) {
|
|
295
|
+
if (e.code === "EPERM") child.kill(sig);
|
|
296
|
+
else if (e.code !== "ESRCH") throw e;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// One command, `sh -c` from `cwd`, in a process group of its own, its output
|
|
301
|
+
// passed through and its tail kept for the counts. A signal that stops it is
|
|
302
|
+
// its number plus 128. `run` carries the child to the signal handlers, and the
|
|
303
|
+
// command's duration to the kill message.
|
|
285
304
|
function runCommand(run, command, cwd, env) {
|
|
286
305
|
return new Promise((resolve) => {
|
|
287
306
|
let tail = "";
|
|
288
307
|
const keep = (chunk) => {
|
|
289
308
|
tail = (tail + chunk).slice(-TAIL_BYTES);
|
|
290
309
|
};
|
|
291
|
-
const child = spawn("sh", ["-c", command], { cwd, env, stdio: ["ignore", "pipe", "pipe"] });
|
|
310
|
+
const child = spawn("sh", ["-c", command], { cwd, env, stdio: ["ignore", "pipe", "pipe"], detached: true });
|
|
292
311
|
run.child = child;
|
|
293
312
|
const startedAt = Date.now();
|
|
294
313
|
child.stdout.setEncoding("utf8");
|