Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Process & ProcessId

ProcessId

A unique identifier assigned by ProcessManager to each spawned process. Implemented as a u64 newtype.

ProcessId is generated atomically from an internal counter in ProcessManager. It is unique within a single ProcessManager instance - no two processes will share the same ProcessId.

Trait Implementations

  • Display - formats as a number
  • PartialEq, Eq, Hash - comparison and hashing
  • Clone, Copy - lightweight value type

Usage

#![allow(unused)]
fn main() {
// ProcessId is returned by start()
let id = manager.start("task", &config)?;

// Used for stop(), get(), etc.
manager.stop(id)?;
let process = manager.get(id);
}

Process

A handle to a managed child process. Stored in ProcessManager’s DashMap and accessed via get_info() which returns a ProcessInfo snapshot.

Lifecycle

graph TD
    classDef default fill: #1e1e1e, stroke: #333333, stroke-width: 1px, color: #ffffff
    classDef start fill: #89fc00, stroke: #333333, stroke-width: 2px, color: #000
    classDef running fill: #00a1e4, stroke: #ffffff, stroke-width: 2px, color: #ffffff
    classDef signal fill: #f5b700, stroke: #333333, stroke-width: 2px, color: #000000
    classDef stop fill: #dc0073, stroke: #333333, stroke-width: 2px, color: #ffffff
    classDef done fill: #04e762, stroke: #333333, stroke-width: 1px, color: #000
    classDef failed fill: #dc0073, stroke: #333333, stroke-width: 1px, color: #ffffff

    A["start()"] --> B["Starting<br/>transient"]
    B --> C["Running<br/>in DashMap"]
    B -->|"spawn fails"| F["Failed"]
    C -->|"send_signal()"| C
    C -->|"stop()"| D["Stopping<br/>SIGTERM sent"]
    C -->|"restart()"| G["Restarting"]
    C -->|"process exits<br/>(reaper detects)"| E["ProcessExitEvent"]
    D -->|"exits normally"| H["Stopped"]
    D -->|"exits with error"| I["Crashed"]
    G -->|"stop old, start new"| B
    E --> E2["Removed from<br/>DashMap"]
    H --> E2
    I --> E2
    F --> E2

    class A start
    class B running
    class C running
    class D stop
    class E signal
    class E2 done
    class F failed
    class G signal
    class H done
    class I done

Fields

FieldTypeDescription
idProcessIdUnique identifier assigned by ProcessManager
pidu32OS process ID
program_nameStringProgram name (for error reporting)
labelLabelLabel under which the process was started
terminate_on_exitboolWhether to terminate on ProcessManager drop
configProcessConfigThe configuration this process was started with
childOption<Child>The std::process::Child handle (always Some)
stateProcessStateThe current lifecycle state (updated lazily by state(), explicitly by stop() / restart())

Methods

MethodReturnsDescription
is_running()boolNon-blocking check via try_wait() - true if still running (delegates to state().is_alive())
state()ProcessStateNon-blocking check via try_wait() - returns the current lifecycle state, updating it if the process has exited
send_signal(signal)Result<(), nix::Error>Send a signal to the process via nix::sys::signal::kill
force_kill()Result<(), nix::Error>Send SIGKILL immediately

Clone Behavior

Process implements Clone manually because std::process::Child does not implement Clone. The clone shares the PID and config but does not duplicate the Child handle - the clone’s child field is None. This is sufficient for read-only access patterns (checking is_running(), reading PID/label).

Usage

#![allow(unused)]
fn main() {
let id = manager.start("task", &config)?;

// Access via DashMap guard
let process = manager.get(id).unwrap();
println!("PID: {}, Label: {}", process.pid, process.label);
println!("Running: {}", process.is_running());
println!("State: {}", process.state);
drop(process); // Release DashMap guard

// Stop the process
manager.stop(id)?;
}