process
Subprocess spawning. Cross-platform: fork + execvp on POSIX, CreateProcess on Windows, selected by target.
| Item | Import |
|---|---|
Command, Stdio, Output | import std::process::command; |
Child, ExitStatus, ChildStdin, ... | import std::process::child; |
Signal, SigNo | import std::process::signal; |
Command
The builder. Configure it, then finish with spawn, output, or status.
import std::process::command;
mut cmd: Command = Command::new(Str::new("git"));
cmd.arg(Str::new("rev-parse"));
cmd.arg(Str::new("HEAD"));
cmd.stdout(Stdio::Piped);
match (cmd.output()) {
Result::Ok(out) => { /* out.stdout() is a Slice<u8> */ }
Result::Err(e) => { /* IoError */ }
}
cmd.drop();
| Method | Notes |
|---|---|
static new(program: Str) | The program is resolved against $PATH at spawn time; pass an absolute path to skip the lookup. |
arg(value: Str) | Append one argument. |
env(key: Str, value: Str) | Set a variable for the child. |
env_clear() | Do not inherit the parent's environment — only env() entries reach the child. |
cwd(path: Str) | Working directory for the child. |
stdin / stdout / stderr(setting: Stdio) | Wire up the standard streams. |
Finishing
| Method | Returns | Notes |
|---|---|---|
spawn() | Result<Child, IoError> | Fork, configure, exec. You must eventually wait. |
output() | Result<Output, IoError> | Spawn, wait, and collect stdout and stderr. The "run this and tell me what it printed" case. |
status() | Result<ExitStatus, IoError> | Spawn and wait; streams go wherever you configured them. |
Output exposes status() -> ExitStatus, stdout() -> Slice<u8>, and stderr() -> Slice<u8>. Both slices borrow the Output and are valid only until it drops — copy out anything you need to keep.
Stdio
type enum Stdio {
Inherit; // share the parent's fd (the default)
Null; // redirect to / from /dev/null
Piped; // create a pipe; the parent's end lands in Child::stdin / stdout / stderr
Fd(i32); // use a specific fd; ownership transfers
}
With Fd, the spawn dups the descriptor into the child and closes it in the parent.
If
execvpfails in the child, it exits with 127 — the standard "command not found" status — so the parent sees that rather than a hang.
Child
A running subprocess, produced by spawn. It holds the pid and whichever pipe ends you asked for, exposed as stdin: Option<ChildStdin>, stdout: Option<ChildStdout>, and stderr: Option<ChildStderr>.
| Method | Returns | Notes |
|---|---|---|
id() | i32 | |
wait() | Result<ExitStatus, IoError> | Blocks. Closes stdin first so the child sees EOF. |
try_wait() | Result<Option<ExitStatus>, IoError> | Ok(None) means still running. |
kill() | Result<(), IoError> | SIGKILL on POSIX. Does not wait. |
send_signal(sig: Signal) | Result<(), IoError> |
wait closing stdin first is deliberate: it is deadlock-avoidant for a child that reads all of stdin before writing anything to stdout.
ChildStdin implements Write; ChildStdout and ChildStderr implement Read. Dropping ChildStdin closes the pipe, which is what signals EOF to the child.
Reaping
Every Child should have wait — or kill then wait — called before it drops.
Child::drop closes any captured pipe ends and makes a non-blocking best-effort reap. If the child has already exited, its zombie is released there. If it is still running, a destructor cannot block, so the child stays detached and reaping it remains your responsibility. That closes the common "spawn, child finishes, drop without wait" leak without ever blocking.
ExitStatus
POSIX packs a normal exit and a signal death into one status word; ExitStatus is the decoded form.
| Method | Returns | Notes |
|---|---|---|
success() | boolean | Exited with status 0. |
exit_code() | Option<i32> | None if killed by a signal. |
terminating_signal() | Option<i32> | Some if killed by a signal. |
Signal
Signal wraps an i32 so the compiler catches passing a pid where a signal was expected. The common ones have named constructors — hangup, interrupt, quit, illegal, trap, abort, bus, floating_point, kill, segfault, pipe, alarm, terminate, child, cont, user1, user2 — and arbitrary numbers go through from_i32. The numbers match Linux x86-64.
Signal handling — installing a handler with
sigaction— is not modelled here. The moment a program installs handlers it crosses into async-signal safety, reentrant allocation, and interaction with every other stdlib primitive; that is a separate design problem.