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::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 canawait
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 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 new(proc_id: ProcId, child: Child) -> Self
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 anArc<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.
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::status
for 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 pid(&self) -> Option<u32>
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.
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_tailers(&self, out: Option<LogTailer>, err: Option<LogTailer>)
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, '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,
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 afterSIGTERM
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,
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 afterSIGKILL
.Err(TerminateError)
if already exited, signaling failed, or the channel was lost.
Source§type Agent = ProcMeshAgent
type Agent = ProcMeshAgent
Source§type TerminalStatus = ProcStatus
type TerminalStatus = ProcStatus
Source§fn addr(&self) -> Option<ChannelAddr>
fn addr(&self) -> Option<ChannelAddr>
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