Cross-platform subprocess supervisor with layered, identity-safe termination.
Remarks
Termination layers
Protocol interrupt: a run with a StdinSession keeps stdin open as the
CLI's protocol channel. Cancellation, deadlines and server shutdown ask the CLI to
end its turn over that protocol; the session closes stdin on the terminal event and
the CLI exits by itself, cleaning up its own children.
Forced stop of the owned root: when the CLI has not exited within the grace
period, terminateProcessTree stops it. Windows uses proc.kill(), which
calls TerminateProcess on the handle Node holds since spawn. POSIX signals the
detached process group with SIGTERM, then SIGKILL.
No tree guessing: no process is ever selected by PID or parent PID. There is no
snapshot, polling or name list. On Windows, libuv places every non-detached child in
a KILL_ON_JOB_CLOSE job, so a chain of Node processes dies with its root.
Descendants created by native backends are the backend's responsibility.
Bounds
UTF-8 decoding is split-safe (StringDecoder), stdout/stderr are capped
(maxBufferBytes, 512 KiB) and the prompt is capped (maxInputBytes, 4 MiB).
After the root exits, a descendant that still holds stdout/stderr cannot delay the
result beyond PIPE_DRAIN_MS.
Cross-platform subprocess supervisor with layered, identity-safe termination.
Remarks
Termination layers
proc.kill(), which callsTerminateProcesson the handle Node holds since spawn. POSIX signals the detached process group withSIGTERM, thenSIGKILL.KILL_ON_JOB_CLOSEjob, so a chain of Node processes dies with its root. Descendants created by native backends are the backend's responsibility.Bounds
UTF-8 decoding is split-safe (
StringDecoder), stdout/stderr are capped (maxBufferBytes, 512 KiB) and the prompt is capped (maxInputBytes, 4 MiB). After the root exits, a descendant that still holds stdout/stderr cannot delay the result beyond PIPE_DRAIN_MS.