Skip to content

node:child_process: honor spawn and exec option semantics beyond cwd/env/shell #2555

@andrewtdiz

Description

@andrewtdiz

Summary

Perry's node:child_process implementation now has real spawn, fork, exec, execFile, and sync helpers, but the option handling is still limited to cwd, env, and shell. Current Node exposes a much wider option contract across these APIs, including stdio, input, timeout, maxBuffer, killSignal, signal, argv0, detached, uid, gid, and platform flags.

That means code using standard Node child-process controls can compile against Perry's surface but run with materially different behavior: stdio is always piped for live spawn/fork, timeouts and AbortSignals are ignored, sync input is not fed to stdin, maxBuffer limits are not enforced, uid/gid are not applied, and kill-signal/argv0/detached semantics are absent.

Evidence

  • Current Node docs list the broader option surface across child_process.exec, execFile, fork, spawn, execSync, execFileSync, and spawnSync, including uid/gid, stdio, input, signal, timeout, killSignal, maxBuffer, argv0, and related platform flags: https://nodejs.org/api/child_process.html
  • crates/perry-runtime/src/child_process/mod.rs:1118-1122 states the current helpers apply only common host-portable options and explicitly says anything not listed, including stdio, timeout, and maxBuffer, is still ignored.
  • crates/perry-runtime/src/child_process/mod.rs:1137-1172 implements cp_apply_options() with only cwd and env handling.
  • crates/perry-runtime/src/child_process/mod.rs:1186-1220 adds shell handling around cp_build_command() and then delegates back to the limited cp_apply_options() path.
  • crates/perry-runtime/src/child_process/reactor.rs:357-409 always creates stdin/stdout/stderr pipe objects and configures the live child with Stdio::piped() regardless of a user stdio option.
  • crates/perry-runtime/src/child_process/fork.rs:56-119 similarly always constructs stdio pipe objects plus fd 3 IPC and applies only the same limited options before forcing all standard streams to Stdio::piped().
  • test-files/test_parity_child_process.ts:100-128 currently probes only basic ChildProcess shapes and does not exercise these option semantics.

Duplicate check

Searched issues and PRs for:

  • child_process stdio timeout maxBuffer input killSignal AbortSignal uid gid argv0 detached windowsHide
  • child_process options stdio timeout maxBuffer
  • subprocess Symbol.dispose child_process

I found no open or closed tracker for this remaining option-semantics gap. This is separate from the closed streaming/IPC work around spawn/fork (#1933/#1934) and from the existing process-side IPC issue (#2529).

Acceptance sketch

  • spawn / fork respect Node stdio forms and expose subprocess.stdin/stdout/stderr/stdio nullability accordingly.
  • spawn / fork honor argv0, detached, uid, gid, signal, timeout, and killSignal where supported by the host platform.
  • exec / execFile / sync variants honor timeout, maxBuffer, killSignal, signal, uid, gid, and input/stdio behavior where applicable.
  • Unsupported platform cases should fail with Node-shaped errors or documented Node-compatible no-op behavior rather than silently ignoring options.
  • Add parity tests that cover deterministic cases: stdio: 'ignore'/array nullability, spawnSync({ input }), small maxBuffer, timeout/AbortSignal termination, and option validation.

Note: this issue was confirmed from committed source and current Node docs; no local target/release/perry binary was available in this checkout for a fresh runtime probe.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions