Files
vercel-labs--zerolang/docs/articles/modules/proc.md
T
wehub-resource-sync e7738de6d2
CI / Deep Native Runtime Cases (1/6) (push) Has been skipped
CI / Native Preflight (push) Failing after 1s
CI / Native Runtime Cases (1/2) (push) Failing after 0s
CI / Native Runtime Cases (2/2) (push) Failing after 1s
CI / Native Metadata Reports (push) Failing after 0s
CI / Native Direct Backend Artifacts (push) Failing after 0s
CI / Native Sanitizer Smoke (push) Failing after 1s
CI / Command Contract Snapshots (push) Failing after 1s
CI / Deep Conformance Suite (push) Has been skipped
CI / Graph Build Perf (push) Failing after 1s
CI / Deep Native Preflight (push) Has been skipped
CI / Deep Native Runtime Cases (2/6) (push) Has been skipped
CI / Deep Native Runtime Cases (3/6) (push) Has been skipped
CI / Conformance Suite (push) Failing after 1s
CI / Workspace Checks (push) Failing after 0s
CI / Deep Native Runtime Cases (5/6) (push) Has been skipped
CI / Deep Native Runtime Cases (6/6) (push) Has been skipped
CI / Deep Native Runtime Cases (4/6) (push) Has been skipped
CI / Deep Graph Build Perf (push) Has been skipped
chore: import upstream snapshot with attribution
2026-07-13 12:29:30 +08:00

8.6 KiB

When To Use std.proc

In Zerolang, use std.proc for hosted process helpers behind explicit process capability boundaries. The surface is host-only and supports both status-style helpers and owned child handles for incremental I/O.

Runnable today:

API Return Notes
std.proc.spawn(command) ProcStatus Runs an argv-style command with inherited stdio through the explicit proc capability surface and returns its status.
std.proc.spawnInherit(command) ProcStatus Runs an argv-style command while inheriting stdin, stdout, and stderr from the parent process.
std.proc.spawnInheritArgs(program, args, cwd, env) ProcStatus Runs a program path plus newline-separated argv entries while inheriting stdio, using a working directory and newline-separated KEY=value environment bindings.
std.proc.exitCode(status) i32 Reads the process status code.
std.proc.succeeded(status) Bool Reports whether the status exit code is 0.
std.proc.failed(status) Bool Reports whether the status exit code is nonzero.
std.proc.runOk(command) Bool Spawns a hosted command and reports whether the resulting status succeeded.
std.proc.runCode(command) i32 Spawns a hosted command and returns its exit code.
std.proc.capture(command, buffer) Maybe<usize> Runs an argv-style command and captures stdout into caller storage. Returns null on parse failure, spawn failure, nonzero exit, unsupported target, or output truncation.
std.proc.captureArgs(program, args, buffer) Maybe<usize> Runs a program path plus newline-separated argv entries and captures stdout into caller storage.
std.proc.captureFiles(command, stdoutPath, stderrPath) ProcStatus Runs an argv-style command and writes stdout and stderr to hosted paths. Returns 127 when the command cannot be parsed, spawned, waited on, or the output files cannot be opened.
std.proc.captureFilesArgs(program, args, stdoutPath, stderrPath) ProcStatus Runs a program path plus newline-separated argv entries and redirects stdout and stderr to hosted paths.
std.proc.spawnChild(command) ProcChild Starts a hosted child process with piped stdin, stdout, and stderr. Returns an invalid handle when the process cannot be created.
std.proc.spawnChildIn(command, cwd) ProcChild Starts a hosted child process in a working directory with piped stdin, stdout, and stderr. Returns an invalid handle when the cwd is invalid or the process cannot be created.
std.proc.spawnChildInEnv(command, cwd, env) ProcChild Starts a hosted child process in a working directory with piped stdin/stdout/stderr and explicit newline-separated KEY=value environment bindings.
std.proc.spawnChildArgs(program, args, cwd, env) ProcChild Starts a hosted child process from a program path plus newline-separated argv entries, working directory, and newline-separated KEY=value environment bindings.
std.proc.childValid(child) Bool Reports whether the handle currently names an open child slot.
std.proc.running(child) Bool Polls the child process without blocking.
std.proc.wait(child) ProcStatus Waits for process exit and returns its status.
std.proc.kill(child) Bool Sends the child a termination signal on supported hosts.
std.proc.interrupt(child) Bool Sends the child an interrupt signal on supported hosts.
std.proc.close(child) Bool Closes the handle and any remaining pipes.
std.proc.closeStdin(child) Bool Closes the child stdin pipe while keeping stdout, stderr, and status available.
std.proc.pid(child) i32 Returns the hosted process id for a child handle, or 0 when unavailable.
std.proc.pidRunning(pid) Bool Reports whether a hosted process id appears to be running.
std.proc.killPid(pid) Bool Sends a termination signal to a hosted process id on supported hosts.
std.proc.interruptPid(pid) Bool Sends an interrupt signal to a hosted process id on supported hosts.
std.proc.killGroupPid(pid) Bool Sends a termination signal to the hosted process group whose id is pid on supported hosts.
std.proc.interruptGroupPid(pid) Bool Sends an interrupt signal to the hosted process group whose id is pid on supported hosts.
std.proc.readStdout(child, buffer) Maybe<usize> Nonblocking read from the child's stdout pipe into caller storage. Returns null when no bytes are currently available or the stream is closed.
std.proc.readStderr(child, buffer) Maybe<usize> Nonblocking read from the child's stderr pipe into caller storage. Returns null when no bytes are currently available or the stream is closed.
std.proc.writeStdin(child, bytes) Maybe<usize> Nonblocking write to the child's stdin pipe. Returns null when the stream is not writable.

Metadata labels:

  • effects: proc
  • allocation behavior: child handles may keep runtime-owned pipe buffers while wait drains stdout, stderr, or PTY output
  • target support: hosted targets with the proc capability
  • error behavior: spawn, spawnInherit, captureFiles, and wait return ProcStatus; exitCode is infallible; capture and child I/O helpers return null when they cannot produce a complete result
  • ownership notes: ProcChild values name runtime-owned process slots; call wait when process status matters and close when the handle is no longer needed
  • example: examples/std-platform.graph

Example

pub fn main(world: World) -> Void raises {
    let status: ProcStatus = std.proc.spawn("zero-noop")
    var storage: [64]u8 = [0_u8; 64]
    let captured: Maybe<usize> = std.proc.capture("printf proc-capture", storage)
    let files: ProcStatus = std.proc.captureFiles("sh -c 'printf proc-out; printf proc-err >&2'", ".zero/proc.out", ".zero/proc.err")
    if std.proc.succeeded(status) && std.proc.succeeded(files) && std.proc.runOk("sh -c true") && std.proc.runCode("sh -c true") == 0 && captured.has {
        check world.out.write("proc ok\n")
    }
}

Incremental child I/O uses caller-owned buffers:

pub fn main(world: World) -> Void raises {
    let child: ProcChild = std.proc.spawnChild("zero-noop")
    var stdoutStorage: [64]u8 = [0_u8; 64]
    let out: Maybe<usize> = std.proc.readStdout(child, stdoutStorage)
    if out.has {
        check world.out.write("child stdout available\n")
    }
    let pid: i32 = std.proc.pid(child)
    let status: ProcStatus = std.proc.wait(child)
    let closed: Bool = std.proc.close(child)
    if pid > 0 && std.proc.succeeded(status) && closed {
        check world.out.write("child ok\n")
    }
}

Design Notes

std.proc requires a hosted target that advertises the proc capability. Targets without process support, including Windows hosts until their process runtime is implemented, must reject process helpers before code generation.

They should not compile a placeholder process implementation.

capture and captureFiles do not invoke a shell. They split simple argv-style command text and support quoted arguments. capture captures stdout only into caller storage. captureFiles redirects stdout and stderr to separate hosted paths.

spawnInherit uses the same argv-style parser and leaves stdin, stdout, and stderr connected to the parent process. spawnInheritArgs uses an explicit program plus newline-separated argv entries, working directory, and environment block. Use inherited stdio for editor, pager, and terminal program launches where captured pipes would be the wrong interface.

Child handles use the same command parser when created from command text. The *Args helpers avoid command-text parsing: program is argv[0], and each non-empty line in args becomes one following argv entry with spaces preserved. captureArgs captures stdout into caller storage, captureFilesArgs redirects stdout and stderr to hosted paths, and spawnChildArgs returns nonblocking pipes so event loops can poll process state and terminal input without owning threads. wait drains child output into the handle before reaping so post-wait readStdout and readStderr calls can still consume buffered data.

Hosted child helpers start children in their own process group where the target platform supports it. Use killGroupPid or interruptGroupPid when a stored pid should stop a command tree instead of only the direct parent process.

spawnChildInEnv, spawnInheritArgs, and spawnChildArgs accept a newline-separated env block such as "TOKEN=...\nMODE=batch". Empty lines are ignored. Invalid entries or oversized env blocks make the helper fail: status helpers return an error status and child helpers return an invalid handle.