ProcessConfig
ProcessConfig is the unified configuration for spawning a child process, built via TypedBuilder.
Overview
ProcessConfig encapsulates everything ProcessManager::start() needs to spawn a child process:
- The command to run and its arguments
- Environment variables and working directory
- Process behavior flags (forked, shell, terminate_on_exit, restart_on_exit)
- Signal configuration (kill_signal, terminate_timeout)
- Standard I/O configuration (stdin, stdout, stderr)
- Optional Wayland socket binding
The TypedBuilder pattern enforces required fields at compile time - only command is required. All other fields have sensible defaults.
Fields
| Field | Type | Default | Description |
|---|---|---|---|
command | String | (required) | Program name or path. Resolved via which if not absolute. |
args | Vec<String> | vec![] | Command-line arguments passed to the program |
env | HashMap<String, String> | HashMap::new() | Additional environment variables merged into the child’s environment |
working_dir | Option<PathBuf> | None | Working directory for the child process |
shell | bool | false | Run command via sh -c instead of direct execution |
forked | bool | false | Detach via setsid() in pre_exec - process gets its own session |
terminate_on_exit | bool | false | Kill this process when ProcessManager is dropped |
kill_signal | KillSignal | Sigterm | Signal to send on termination (Sigterm or Sigkill) |
terminate_timeout_ms | u64 | 5000 | Grace period (ms) before escalating from SIGTERM to SIGKILL |
restart_on_exit | bool | false | Enable automatic restart on exit (requires reaper thread) |
restart_trigger | RestartTrigger | CrashOnly | When to restart: CrashOnly (non-zero exit) or Always (any exit) |
restart_policy | RestartPolicy | Immediate | Restart strategy: Immediate or Backoff(BackoffConfig) |
supervisor_strategy | SupervisorStrategy | OneForOne | Controls which processes are restarted on crash: OneForOne, OneForAll, or RestForOne |
depends_on | Vec<DependencyRef> | vec![] | Dependencies to wait for before starting. DependencyRef::Label or DependencyRef::Id |
dependency_timeout_ms | u64 | 30000 | Timeout (ms) for dependencies to become Running before failing |
cascade_stop | bool | true | When true, stopping a process also stops its dependents |
stdin | StdioConfig | Null | Standard input configuration |
stdout | StdioConfig | Null | Standard output configuration |
stderr | StdioConfig | Null | Standard error configuration |
socket | Option<Socket> | None | Wayland socket - sets WAYLAND_DISPLAY in child environment |
Builder Flow
graph TD
classDef default fill: #1e1e1e, stroke: #333333, stroke-width: 1px, color: #ffffff
classDef required fill: #dc0073, stroke: #333333, stroke-width: 2px, color: #ffffff
classDef optional fill: #00a1e4, stroke: #ffffff, stroke-width: 1px, color: #ffffff
classDef build fill: #89fc00, stroke: #333333, stroke-width: 2px, color: #000
A[".command()"] --> B[".args()"]
B --> C[".env()"]
C --> D[".forked()"]
D --> E[".kill_signal()"]
E --> F[".stdout()"]
F --> G[".socket()"]
G --> H[".build()"]
class A required
class B optional
class C optional
class D optional
class E optional
class F optional
class G optional
class H build
Usage
Minimal
#![allow(unused)]
fn main() {
use process_manager::ProcessConfig;
let config = ProcessConfig::builder()
.command("echo".to_string())
.build();
}
Full
#![allow(unused)]
fn main() {
use process_manager::{ProcessConfig, StdioConfig, KillSignal, RestartPolicy, RestartTrigger, BackoffConfig};
use process_manager_socket::Socket;
use std::path::PathBuf;
use std::collections::HashMap;
let mut env = HashMap::new();
env.insert("MY_VAR".to_string(), "value".to_string());
let config = ProcessConfig::builder()
.command("my-app".to_string())
.args(vec!["--verbose".to_string(), "--port".to_string(), "8080".to_string()])
.env(env)
.working_dir(PathBuf::from("/tmp"))
.shell(false)
.forked(true)
.terminate_on_exit(true)
.kill_signal(KillSignal::Sigterm)
.terminate_timeout_ms(3000)
.restart_on_exit(true)
.restart_trigger(RestartTrigger::CrashOnly)
.restart_policy(RestartPolicy::Backoff(BackoffConfig::default()))
.stdin(StdioConfig::Null)
.stdout(StdioConfig::Piped)
.stderr(StdioConfig::Piped)
.socket(Some(Socket::from(PathBuf::from("/run/user/1000/wayland-0"))))
.build();
}
Defaults Explained
shell = false: Direct execution is safer and faster. Useshell = trueonly when you need shell features (pipes, redirects, variable expansion).forked = false: By default, processes share the parent’s controlling terminal. Useforked = truefor daemons that should survive terminal close.terminate_on_exit = false: By default, processes are left running when the manager is dropped. Usetruefor processes that should be cleaned up with the manager.kill_signal = Sigterm: Graceful termination by default. The process can catchSIGTERMand clean up.terminate_timeout_ms = 5000: 5 seconds grace period beforeSIGKILL. Adjust for processes that need more cleanup time.restart_on_exit = false: By default, processes are not automatically restarted. Enable withrestart_on_exit(true)and use the reaper thread for automatic restart with backoff.restart_trigger = CrashOnly: By default, only crashed processes (non-zero exit) are restarted. UseAlwaysto also restart on clean exits.restart_policy = Immediate: By default, restarts happen immediately. UseBackoff(BackoffConfig)for exponential backoff with rate limiting.stdio = Null: All streams are null by default, suitable for background processes. UsePipedfor output capture orInheritfor debugging.socket = None: No Wayland binding by default. Set when spawning Wayland clients.
Serde
ProcessConfig implements Serialize and Deserialize, making it suitable for JSON/TOML configuration files. All nested types (StdioConfig, KillSignal, Socket) also implement serde traits.