mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-27 06:43:19 +08:00
Fire spawn listeners for a child that exits before its first poll pass (#1986)
This commit is contained in:
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/corpus/7640-child-spawn-before-fast-exit.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
@@ -2780,7 +2780,8 @@ static void scr_child_settle(ScrChild *c) {
|
||||
scr_children_reffed_n--;
|
||||
}
|
||||
if (c->state == SCR_CHILD_EXITED) {
|
||||
scr_child_stream_drain_now(c->out_stream);
|
||||
if (!c->spawn_done) scr_child_fire_spawn(c);
|
||||
if (!scr_exc_pending()) scr_child_stream_drain_now(c->out_stream);
|
||||
if (!scr_exc_pending()) scr_child_stream_drain_now(c->err_stream);
|
||||
if (!scr_exc_pending()) scr_ipc_settle(c->ipc);
|
||||
}
|
||||
@@ -5607,9 +5608,12 @@ static void scr_child_settle(ScrChild *c) {
|
||||
/* Streams first, settled after: an exit listener registered from a
|
||||
* draining 'data'/'end' callback still fires below, like Node's. The
|
||||
* SPAWN-FAILURE path skips the drain — Node fires 'error' first and
|
||||
* the streams' immediate EOF delivers 'end' on the next turn. */
|
||||
* the streams' immediate EOF delivers 'end' on the next turn. A child
|
||||
* spawned during this pass can exit before the next pass fires 'spawn';
|
||||
* Node emits 'spawn' before any data or 'exit', so it fires here first. */
|
||||
if (c->state == SCR_CHILD_EXITED) {
|
||||
scr_child_stream_drain_now(c->out_stream);
|
||||
if (!c->spawn_done) scr_child_fire_spawn(c);
|
||||
if (!scr_exc_pending()) scr_child_stream_drain_now(c->out_stream);
|
||||
if (!scr_exc_pending()) scr_child_stream_drain_now(c->err_stream);
|
||||
if (!scr_exc_pending()) scr_ipc_settle(c->ipc);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// A child spawned from a 'close' listener that exits before the listener
|
||||
// returns still emits 'spawn' before 'exit'.
|
||||
import { spawn } from "node:child_process";
|
||||
|
||||
function busyWait(ms: number): void {
|
||||
const end = Date.now() + ms;
|
||||
while (Date.now() < end) {}
|
||||
}
|
||||
|
||||
const events: string[] = [];
|
||||
spawn("sh", ["-c", "exit 0"], { stdio: "ignore" }).on("close", () => {
|
||||
const child = spawn("sh", ["-c", "exit 4"], { stdio: "ignore" });
|
||||
child.on("spawn", () => events.push("spawn"));
|
||||
child.on("exit", (code) => events.push(`exit ${code}`));
|
||||
child.on("close", (code) => {
|
||||
events.push(`close ${code}`);
|
||||
console.log(events.join(", "));
|
||||
});
|
||||
busyWait(300);
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
{ "plain": 2600, "san": 4000 }
|
||||
Reference in New Issue
Block a user