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

123 lines
8.6 KiB
Markdown

## 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
```zero
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:
```zero
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.