Documentation
¶
Overview ¶
Package proc is the process boundary: the one subprocess gateway in CSF. Starting another program crosses into another address space through fork and exec, so it happens only through a capability granted by the binary that owns the process, and this is the only package in candace/ that imports os/exec.
A binary constructs one HostLauncher and passes it, as an ILauncher, to whatever needs to run a program; a service receives the capability in its constructor and never builds an exec.Cmd itself. The gateway owns the whole life of a child:
- launch: an argument vector, never a shell string, in an explicit directory and environment;
- input and output: caller-supplied readers and writers, or captured output returned as a structured Result;
- cancellation: the context passed to HostLauncher.Run or HostLauncher.Start bounds the child, and canceling it kills the child's whole process group, so a shell's own children die with it;
- waiting and cleanup: HostLauncher.Run always reaps its child, and a started Process is reaped by Process.Wait, so no child is left a zombie.
The package starts no goroutines of its own. The copying goroutines os/exec runs for non-file writers, and the one that watches a context, are owned by the call: they start in Run or Start and are joined by the Wait that completes it.
Index ¶
- Constants
- Variables
- type Command
- type ExitError
- type HostLauncher
- type HostLauncherOption
- type ILauncher
- type Process
- func (process *Process) Kill() error
- func (process *Process) Pid() int
- func (process *Process) Resize(size TerminalSize) error
- func (process *Process) Signal(signal os.Signal) error
- func (process *Process) Stdout() io.Reader
- func (process *Process) Terminal() *os.File
- func (process *Process) Wait() (Result, error)
- type Result
- type TerminalSize
Constants ¶
const ( // DefaultWaitDelay bounds how long Wait keeps reading a canceled child's // output pipes after the kill: a grandchild that escaped the group must // not hold the caller forever. DefaultWaitDelay = 5 * time.Second // DefaultDiagnosticBytes bounds captured standard error. DefaultDiagnosticBytes = 64 << 10 )
Variables ¶
var ( // ErrTerminalRun is returned when a terminal is requested from Run: an // interactive terminal belongs to a started [Process]. ErrTerminalRun = errors.New("ipc/proc: a terminal command must be started, not run") // ErrStreamConflict is returned for a command whose stream fields // contradict each other. ErrStreamConflict = errors.New("ipc/proc: conflicting standard stream configuration") // ErrExecutableRequired is returned for a command with no executable. ErrExecutableRequired = errors.New("ipc/proc: executable is required") // ErrInvalidOption is returned by NewHostLauncher for a nil or // out-of-range option. ErrInvalidOption = errors.New("ipc/proc: invalid launcher option") // ErrNoTerminal is returned by Resize on a process started without one. ErrNoTerminal = errors.New("ipc/proc: process has no terminal") )
Functions ¶
This section is empty.
Types ¶
type Command ¶
type Command struct {
// Executable is a path, or a name resolved on PATH.
Executable string
// Arguments follow the executable in the argument vector.
Arguments []string
// Directory is the working directory; empty means the caller's.
Directory string
// Environment replaces the inherited environment when non-nil.
Environment []string
// ExtraEnvironment is appended to the environment the child receives,
// inherited or replaced, so a caller adds a variable without reading the
// process environment itself.
ExtraEnvironment []string
// Stdin is the child's standard input; nil means none.
Stdin io.Reader
// Stdout receives standard output. When nil it is captured into
// [Result.Stdout] (unbounded, like exec.Cmd.Output), unless StdoutPipe
// is set on a started process.
Stdout io.Writer
// Stderr receives standard error. When nil it is captured, bounded by the
// launcher's diagnostic limit, into [Result.Stderr] and [ExitError],
// whose message then carries it. A caller whose child's diagnostics may
// hold secrets passes io.Discard to keep them out of every error.
Stderr io.Writer
// StdoutPipe exposes standard output as [Process.Stdout] on a started
// process. Read it to the end before Wait.
StdoutPipe bool
// Terminal attaches the child to a new pseudo-terminal of this size, in
// its own session. Stdin, Stdout and Stderr must be nil: the terminal is
// all three, read and written through [Process.Terminal].
Terminal *TerminalSize
}
Command is one program invocation.
type ExitError ¶
type ExitError struct {
Executable string
Code int
Stderr []byte
// contains filtered or unexported fields
}
ExitError reports a child that ran and exited unsuccessfully.
type HostLauncher ¶
type HostLauncher struct {
// contains filtered or unexported fields
}
HostLauncher is this host's process table, granted as a capability.
func NewHostLauncher ¶
func NewHostLauncher(options ...HostLauncherOption) (*HostLauncher, error)
NewHostLauncher returns the host's process capability.
func (*HostLauncher) LookPath ¶
func (launcher *HostLauncher) LookPath(name string) (string, error)
LookPath resolves name on PATH.
func (*HostLauncher) Run ¶
Run starts command, waits for it, and returns its result. A child that exits unsuccessfully returns an *ExitError; a canceled context kills the child's process group and returns the context's cause. The result carries whatever output was captured in every case.
type HostLauncherOption ¶
type HostLauncherOption func(launcher *HostLauncher) error
HostLauncherOption configures a HostLauncher.
func WithDiagnosticBytes ¶
func WithDiagnosticBytes(limit int64) HostLauncherOption
WithDiagnosticBytes bounds captured standard error.
func WithWaitDelay ¶
func WithWaitDelay(delay time.Duration) HostLauncherOption
WithWaitDelay bounds how long a canceled child's pipes are drained.
type ILauncher ¶
type ILauncher interface {
// Run starts command, waits for it and returns its structured result.
Run(ctx context.Context, command Command) (Result, error)
// Start launches command and returns the running process, which the
// caller must Wait for.
Start(ctx context.Context, command Command) (*Process, error)
// LookPath resolves an executable name the way Run would.
LookPath(name string) (string, error)
}
ILauncher runs programs. It is the process-boundary capability.
type Process ¶
type Process struct {
// contains filtered or unexported fields
}
Process is one started child. Exactly one goroutine calls Process.Wait; Process.Kill, Process.Signal and Process.Resize may be called from any goroutine before or during that Wait.
func (*Process) Kill ¶
Kill ends the child and everything it started: its process group, and for a terminal every process in its session, including background jobs a shell moved into groups of their own. It does not wait; Wait reaps the child.
func (*Process) Pid ¶
Pid is the child's process identifier; for a terminal it is also the session and process-group identifier.
func (*Process) Resize ¶
func (process *Process) Resize(size TerminalSize) error
Resize changes a terminal command's window size.
func (*Process) Signal ¶
Signal delivers signal to the child alone, the way an interrupt asks a program to run its own shutdown.
func (*Process) Stdout ¶
Stdout is standard output when the command asked for StdoutPipe, else nil. Read it to the end before Wait.
type Result ¶
type Result struct {
// ExitCode is the child's exit status, or -1 if it was killed by a
// signal or never ran.
ExitCode int
// Stdout is captured standard output when Command.Stdout was nil.
Stdout []byte
// Stderr is captured standard error when Command.Stderr was nil.
Stderr []byte
// StderrTruncated reports that captured standard error exceeded the
// diagnostic limit and only its prefix was kept.
StderrTruncated bool
}
Result is what a finished child left behind.
type TerminalSize ¶
TerminalSize is a pseudo-terminal window in character cells.