Struct BootstrapProcHandle

Source
pub struct BootstrapProcHandle { /* private fields */ }
Expand description

A handle to a proc launched by BootstrapProcManager.

BootstrapProcHandle is a lightweight supervisor for an external process: it tracks and broadcasts lifecycle state, and exposes a small control/observation surface. While it may temporarily hold a tokio::process::Child (shared behind a mutex) so the exit monitor can wait() it, it is not the unique owner of the OS process, and dropping a BootstrapProcHandle does not by itself terminate the process.

What it pairs together:

  • the logical proc identity (ProcId)
  • the live status surface (ProcStatus), available both as a synchronous snapshot (status()) and as an async stream via a tokio::sync::watch channel (watch() / changed())

Responsibilities:

  • Retain the child handle only until the exit monitor claims it, so the OS process can be awaited and its terminal status recorded.
  • Hold stdout/stderr tailers until the exit monitor takes them, then join to recover buffered output for diagnostics.
  • Update status via the mark_* transitions and broadcast changes over the watch channel so tasks can await lifecycle transitions without polling.
  • Provide the foundation for higher-level APIs like wait() (await terminal) and, later, terminate() / kill().

Notes:

  • Manager-level cleanup happens in BootstrapProcManager::drop: it SIGKILLs any still-recorded PIDs; we do not rely on Child::kill_on_drop.

Relationship to types:

  • ProcStatus: live status surface, updated by this handle.
  • [ProcState]/[ProcStopReason] (in alloc.rs): allocator-facing, historical event log; not directly updated by this type.

Implementations§

Source§

impl BootstrapProcHandle

Source

pub fn new(proc_id: ProcId, child: Child) -> Self

Construct a new BootstrapProcHandle for a freshly spawned OS process hosting a proc.

  • Initializes the status to ProcStatus::Starting since the child process has been created but not yet confirmed running.
  • Wraps the provided [Child] handle in an Arc<Mutex<Option<Child>>> so lifecycle methods (wait, terminate, etc.) can consume it later.

This is the canonical entry point used by BootstrapProcManager when it launches a proc into a new process.

Source

pub fn proc_id(&self) -> &ProcId

Return the logical proc identity in the mesh.

Source

pub fn watch(&self) -> Receiver<ProcStatus>

Create a new subscription to this proc’s status stream.

Each call returns a fresh [watch::Receiver] tied to this handle’s internal ProcStatus channel. The receiver can be awaited on (rx.changed().await) to observe lifecycle transitions as they occur.

Notes:

  • Multiple subscribers can exist simultaneously; each sees every status update in order.
  • Use BootstrapProcHandle::status for a one-off snapshot; use watch() when you need to await changes over time.
Source

pub async fn changed(&self)

Wait until this proc’s status changes.

This is a convenience wrapper around [watch::Receiver::changed]: it subscribes internally via BootstrapProcHandle::watch and awaits the next transition. If no subscribers exist or the channel is closed, this returns without error.

Typical usage:

handle.changed().await;
match handle.status() {
    ProcStatus::Running { .. } => { /* now running */ }
    ProcStatus::Stopped { .. } => { /* exited */ }
    _ => {}
}
Source

pub fn pid(&self) -> Option<u32>

Return the OS process ID (pid) for this proc.

If the proc is currently Running, this returns the cached pid even if the Child has already been taken by the exit monitor. Otherwise, it falls back to Child::id() if the handle is still present. Returns None once the proc has exited or if the handle has been consumed.

Source

pub fn status(&self) -> ProcStatus

Return a snapshot of the current ProcStatus for this proc.

This is a live view of the lifecycle state as tracked by BootstrapProcManager. It reflects what is currently known about the underlying OS process (e.g., Starting, Running, Stopping, etc.).

Internally this reads the mutex-guarded status. Use this when you just need a synchronous snapshot; use BootstrapProcHandle::watch or BootstrapProcHandle::changed if you want to await transitions asynchronously.

Source

pub async fn wait_inner(&self) -> ProcStatus

Wait until the proc has reached a terminal state and return it.

Terminal means ProcStatus::Stopped, ProcStatus::Killed, or ProcStatus::Failed. If the current status is already terminal, returns immediately.

Non-consuming: BootstrapProcHandle is a supervisor, not the owner of the OS process, so you can call wait() from multiple tasks concurrently.

Implementation detail: listens on this handle’s watch channel. It snapshots the current status, and if not terminal awaits the next change. If the channel closes unexpectedly, returns the last observed status.

Mirrors tokio::process::Child::wait(), but yields the higher-level ProcStatus instead of an ExitStatus.

Source

pub async fn ready_inner(&self) -> Result<(), ReadyError>

Wait until the proc reaches the ProcStatus::Ready state.

If the proc hits a terminal state (ProcStatus::Stopped, ProcStatus::Killed, or ProcStatus::Failed) before ever becoming Ready, this returns Err(ReadyError::Terminal(status)). If the internal watch channel closes unexpectedly, this returns Err(ReadyError::ChannelClosed). Otherwise it returns Ok(()) when Ready is first observed.

Non-consuming: BootstrapProcHandle is a supervisor, not the owner; multiple tasks may await ready() concurrently. Stopping is not treated as terminal here; we continue waiting until Ready or a terminal state is seen.

Companion to BootstrapProcHandle::wait_inner: wait_inner() resolves on exit; ready_inner() resolves on startup.

Source

pub fn set_tailers(&self, out: Option<LogTailer>, err: Option<LogTailer>)

Trait Implementations§

Source§

impl Clone for BootstrapProcHandle

Source§

fn clone(&self) -> BootstrapProcHandle

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for BootstrapProcHandle

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl ProcHandle for BootstrapProcHandle

Source§

fn ready<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<(), ReadyError<Self::TerminalStatus>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Wait until this proc first reaches the ProcStatus::Ready state.

Returns Ok(()) once Ready is observed.

If the proc transitions directly to a terminal state before becoming Ready, returns Err(ReadyError::Terminal(status)).

If the internal status watch closes unexpectedly before Ready is observed, returns Err(ReadyError::ChannelClosed).

Source§

fn wait<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<Self::TerminalStatus, WaitError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Wait until this proc reaches a terminal ProcStatus.

Returns Ok(status) when a terminal state is observed (Stopped, Killed, or Failed).

If the internal status watch closes before any terminal state is seen, returns Err(WaitError::ChannelClosed).

Source§

fn terminate<'life0, 'async_trait>( &'life0 self, timeout: Duration, ) -> Pin<Box<dyn Future<Output = Result<ProcStatus, TerminateError<Self::TerminalStatus>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Attempt to terminate the underlying OS process.

This drives process-level teardown only:

  • Sends SIGTERM to the process.
  • Waits up to timeout for it to exit cleanly.
  • Escalates to SIGKILL if still alive, then waits a short hard-coded grace period (HARD_WAIT_AFTER_KILL) to ensure the process is reaped.

If the process was already in a terminal state when called, returns [TerminateError::AlreadyTerminated].

§Notes
  • This does not attempt a graceful proc-level stop via ProcMeshAgent or other actor messaging. That integration will come later once proc-level control is wired up.
  • Errors may also be returned if the process PID cannot be determined, if signal delivery fails, or if the status channel is closed unexpectedly.
§Parameters
  • timeout: Grace period to wait after SIGTERM before escalating.
§Returns
  • Ok(ProcStatus) if the process exited during the termination sequence.
  • Err(TerminateError) if already exited, signaling failed, or the channel was lost.
Source§

fn kill<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<ProcStatus, TerminateError<Self::TerminalStatus>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Forcibly kill the underlying OS process with SIGKILL.

This bypasses any graceful shutdown semantics and immediately delivers a non-catchable SIGKILL to the child. It is intended as a last-resort termination mechanism when terminate() fails or when no grace period is desired.

§Behavior
  • If the process was already in a terminal state, returns [TerminateError::AlreadyTerminated].
  • Otherwise attempts to send SIGKILL to the current PID.
  • Then waits for the exit monitor to observe a terminal state.
§Notes
  • This is strictly an OS-level kill. It does not attempt proc-level shutdown via ProcMeshAgent or actor messages. That integration will be layered in later.
  • Errors may be returned if the PID cannot be determined, if signal delivery fails, or if the status channel closes unexpectedly.
§Returns
  • Ok(ProcStatus) if the process exited after SIGKILL.
  • Err(TerminateError) if already exited, signaling failed, or the channel was lost.
Source§

type Agent = ProcMeshAgent

The agent actor type installed in the proc by the manager. Must implement both: Read more
Source§

type TerminalStatus = ProcStatus

The type of terminal status produced when the proc exits. Read more
Source§

fn proc_id(&self) -> &ProcId

The proc’s logical identity on this host.
Source§

fn addr(&self) -> Option<ChannelAddr>

The proc’s address (the one callers bind into the host router).
Source§

fn agent_ref(&self) -> Option<ActorRef<Self::Agent>>

The agent actor reference hosted in the proc.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Any for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

§

fn type_name(&self) -> &'static str

§

impl<T> AnySync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> FutureExt for T

§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<A, M> Handler<IndexedErasedUnbound<M>> for A
where A: Handler<M>, M: Castable,

Source§

fn handle<'life0, 'life1, 'async_trait>( &'life0 mut self, cx: &'life1 Context<'_, A>, msg: IndexedErasedUnbound<M>, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, A: 'async_trait,

Handle the next M-typed message.
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> QuoteExt for T
where T: ?Sized,

§

fn push_quoted<'q, Q, S>(&mut self, _q: Q, s: S)
where Q: QuoteInto<T>, S: Into<Quotable<'q>>,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
Source§

impl<M> Message for M
where M: Debug + Send + Sync + 'static,