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 atokio::sync::watchchannel (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 canawaitlifecycle 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 onChild::kill_on_drop.
Relationship to types:
ProcStatus: live status surface, updated by this handle.- [
ProcState]/[ProcStopReason] (inalloc.rs): allocator-facing, historical event log; not directly updated by this type.
Implementations§
Source§impl BootstrapProcHandle
impl BootstrapProcHandle
Sourcepub fn watch(&self) -> Receiver<ProcStatus>
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::statusfor a one-off snapshot; usewatch()when you need to await changes over time.
Sourcepub async fn changed(&self)
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 */ }
_ => {}
}Sourcepub fn status(&self) -> ProcStatus
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.
Sourcepub async fn wait_inner(&self) -> ProcStatus
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.
Sourcepub async fn ready_inner(&self) -> Result<(), ReadyError>
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.
pub fn set_stream_monitors( &self, out: Option<StreamFwder>, err: Option<StreamFwder>, )
Trait Implementations§
Source§impl Clone for BootstrapProcHandle
impl Clone for BootstrapProcHandle
Source§fn clone(&self) -> BootstrapProcHandle
fn clone(&self) -> BootstrapProcHandle
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for BootstrapProcHandle
impl Debug for BootstrapProcHandle
Source§impl ProcHandle for BootstrapProcHandle
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,
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,
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, 'life1, 'life2, 'async_trait>(
&'life0 self,
cx: &'life1 (impl 'async_trait + Actor),
timeout: Duration,
reason: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<ProcStatus, TerminateError<Self::TerminalStatus>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn terminate<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
cx: &'life1 (impl 'async_trait + Actor),
timeout: Duration,
reason: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<ProcStatus, TerminateError<Self::TerminalStatus>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Attempt to terminate the underlying OS process.
This drives process-level teardown only:
- First attempts graceful shutdown via
ProcAgentif available. - If that fails or times out, delegates to the launcher’s
terminate()method, which handles SIGTERM/SIGKILL escalation.
If the process was already in a terminal state when called,
returns [TerminateError::AlreadyTerminated].
§Parameters
timeout: Grace period to wait after graceful shutdown before escalating.reason: Human-readable reason for termination.
§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,
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.
This bypasses any graceful shutdown semantics and immediately
delegates to the launcher’s kill() method. 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 delegates to the launcher’s
kill()method. - Then waits for the exit monitor to observe a terminal state.
§Returns
Ok(ProcStatus)if the process exited after kill.Err(TerminateError)if already exited, signaling failed, or the channel was lost.
Source§type Agent = ProcAgent
type Agent = ProcAgent
Source§type TerminalStatus = ProcStatus
type TerminalStatus = ProcStatus
Auto Trait Implementations§
impl Freeze for BootstrapProcHandle
impl !RefUnwindSafe for BootstrapProcHandle
impl Send for BootstrapProcHandle
impl Sync for BootstrapProcHandle
impl Unpin for BootstrapProcHandle
impl !UnwindSafe for BootstrapProcHandle
Blanket Implementations§
§impl<T> AnySync for T
impl<T> AnySync for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
Source§impl<A, M> Handler<IndexedErasedUnbound<M>> for A
impl<A, M> Handler<IndexedErasedUnbound<M>> for A
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request§impl<L> LayerExt<L> for L
impl<L> LayerExt<L> for L
§fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
Layered].