Under heavy development. This site describes the intended 1.0 language. Current features and performance vary. Development status
Sn50SnThe SnAPI programming language
Development · Evolving reference

RunProcess

Executes one explicit command synchronously through terminal cleanup. May allocate/spawn/block. Command input backing remains borrowed only through return. No unsafe block, implicit shell or ambient argv/environment/cwd is needed. Timeout/cancellation terminate the owned group and reap the direct child before failure returns; OS uninterruptible work has no promised wall-clock kill bound.

Sn is under heavy development. This reference includes the intended 1.0 design; features may be incomplete in the current compiler. Read the status →

Module std.process

import std.process;

Public declaration contracts and authored examples. A page can document several related symbols. Implementation bodies are excluded.

RunProcess

pub fn RunProcess(Command: readonly ProcessCommand&, Limit: Timeout, Token: CancellationToken) -> Result<ProcessExit, ProcessError>

Executes one explicit command synchronously through terminal cleanup. May allocate/spawn/block. Command input backing remains borrowed only through return. No unsafe block, implicit shell or ambient argv/environment/cwd is needed. Timeout/cancellation terminate the owned group and reap the direct child before failure returns; OS uninterruptible work has no promised wall-clock kill bound. Command: Explicit owned backing borrowed unmodified through return. Limit: Nonnegative exact relative timeout or Endless; rounded upward at the native nanosecond boundary, never silently converted to endless. Token: Owned cooperative cancellation observation, inert by default. Return: Detached normal/abnormal exit, or launch/control/native failure.

Example

module example.process_execution;
from std.process import Arguments, Environment, ProgramInputs, ProcessCommand,
    RunProcess, RunProcessAsync, ProcessError, ProcessFailure;
from std.fs import Path;
from std.text import NativeString;
from std.prelude import Result;
from std.task import Task;
from std.time import Timeout, Seconds;
fn CreateCommand() -> Result<ProcessCommand, ProcessError> {
    var Executable = {
        // Scoped writable carriers end immediately after explicit payload transfer.
        var ExecutableCreation = Path.TryCreate("/bin/sh");
        switch ExecutableCreation {
            case .Ok { Value = Value: mut Path& } => break move(Value);
            case .Err => return .Err { Error = ProcessError { Reason = .OutOfMemory, NativeCode = 0 } };
        }
    };
    var Directory = {
        var DirectoryCreation = Path.TryCreate("/");
        switch DirectoryCreation {
            case .Ok { Value = Value: mut Path& } => break move(Value);
            case .Err => return .Err { Error = ProcessError { Reason = .OutOfMemory, NativeCode = 0 } };
        }
    };
    var Values = Arguments();
    let CommandArguments: str[3] = ["/bin/sh", "-c", "exit 7"];
    for Text in CommandArguments {
        var Argument = {
            var ValueCreation = NativeString.TryCreate(Text);
            switch ValueCreation {
                case .Ok { Value = Value: mut NativeString& } => break move(Value);
                case .Err => return .Err { Error = ProcessError { Reason = .OutOfMemory, NativeCode = 0 } };
            }
        };
        if Values.TryPush(move(Argument)) is .Err { Error = _ } { return .Err { Error = ProcessError { Reason = .OutOfMemory, NativeCode = 0 } }; }
    }
    return .Ok { Value = ProcessCommand(move(Executable), move(Directory), ProgramInputs(move(Values), Environment())) };
}
async fn Main() -> Task<i32> {
    // This example explicitly requires a Linux host with a POSIX shell.
    var Command = {
        var CommandCreation = CreateCommand();
        switch CommandCreation {
            case .Ok { Value = Value: mut ProcessCommand& } => break move(Value);
            case .Err => return 1;
        }
    };
    let Limit = switch Timeout.TryFromDuration(Seconds.Create(2)) { case .Ok { Value = Value } => break Value; case .Err => return 2; };
    let Readonly: readonly ProcessCommand& = Command;
    if Readonly.Executable.IsEmpty || Command.Inputs().Arguments().Length != 3 { return 3; }
    Command.ChangeStandardStreamInheritance(false);
    switch RunProcess(Readonly, Limit) {
        case .Ok { Value = PatternPayload5134 } => {
            switch PatternPayload5134 {
                case .Exited { Code = PatternPayload5135 } if (PatternPayload5135 == 7) => {}
                default => return 4;
            }
        }
        default => return 4;
    }
    switch await RunProcessAsync(move(Command), Limit) {
        case .Ok { Value = PatternPayload5136 } => {
            switch PatternPayload5136 {
                case .Exited { Code = PatternPayload5137 } if (PatternPayload5137 == 7) => {}
                default => return 5;
            }
        }
        default => return 5;
    }
    return 0;
}

RunProcess

pub fn RunProcess(Command: readonly ProcessCommand&) -> Result<ProcessExit, ProcessError>

Supplies the omitted arguments to RunProcess. Note: Defaults: Limit = .Endless, Token = CancellationToken(). Command: Same input, ownership and lifetime contract as the full operation. Return: The full synchronous operation's value or typed failure.

RunProcess

pub fn RunProcess(Command: readonly ProcessCommand&, mut Limit: Timeout) -> Result<ProcessExit, ProcessError>

Supplies the omitted arguments to RunProcess. Note: Defaults: Token = CancellationToken(). Command: Same input, ownership and lifetime contract as the full operation. Limit: Same input, ownership and lifetime contract as the full operation. Return: The full synchronous operation's value or typed failure.

RunProcessAsync

pub async fn RunProcessAsync(mut Command: ProcessCommand, Limit: Timeout, Token: CancellationToken) -> Task<Result<ProcessExit, ProcessError>>

Consumes explicit command ownership and executes on the blocking pool. Command backing and cancellation query remain owned through terminal native cleanup. May allocate/queue; submission never performs native launch/wait on the initiating thread. Resume uses the caller's captured executor. Command: Owned executable/cwd/argv/environment transferred into work. Limit: Exact nonnegative relative native execution allowance or Endless; queue admission time is separate from the native execution allowance. Token: Owned cooperative cancellation observation, inert by default. Return: Unique task yielding detached exit or native/admission/control failure.

RunProcessAsync

pub fn RunProcessAsync(mut Command: ProcessCommand) -> Task<Result<ProcessExit, ProcessError>>

Supplies the omitted arguments to RunProcessAsync. Note: Defaults: Limit = .Endless, Token = CancellationToken(). Command: Same input, ownership and lifetime contract as the full operation. Return: Exact full-operation result; no additional async frame is created.

RunProcessAsync

pub fn RunProcessAsync(mut Command: ProcessCommand, mut Limit: Timeout) -> Task<Result<ProcessExit, ProcessError>>

Supplies the omitted arguments to RunProcessAsync. Note: Defaults: Token = CancellationToken(). Command: Same input, ownership and lifetime contract as the full operation. Limit: Same input, ownership and lifetime contract as the full operation. Return: Exact full-operation result; no additional async frame is created.

Documentation snapshot: October 24, 2026 About versions ↗
Searching Development · language & standard library