Skip to main content

ProcessGroup

Struct ProcessGroup 

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

A container that ties the lifetime of a child-process tree to its own.

Every process spawned into the group — and everything those processes spawn — is killed when the group is dropped (kill-on-close), so an exiting or panicking owner never leaks subprocesses. The containment mechanism is platform-specific and observable via mechanism.

Dropping the group performs an immediate hard kill. For a graceful SIGTERM → wait → SIGKILL teardown (Unix), call shutdown instead — Drop cannot await, so the graceful tier lives in that async method.

The drop guarantee covers every exit that runs destructors (returns, panics with unwinding). If the owner dies abruptlySIGKILL, std::process::abortDrop never runs: on Windows the kernel still kills the tree (the job handle closes with the process), elsewhere that hardening is the opt-in Command::kill_on_parent_death (Linux, direct child only; unavailable on macOS/BSD).

Implementations§

Source§

impl ProcessGroup

Source

pub fn new() -> Result<Self>

Create an empty group with default options.

§Errors

Error::Io if the OS rejects creating the group’s containment primitive (a Job Object on Windows, a cgroup on Linux). The default options set no resource caps, so no limit-enforcement failure can arise.

Source

pub fn with_options(options: ProcessGroupOptions) -> Result<Self>

Create an empty group with the given options.

§Errors

Error::Io if the OS rejects creating the group’s containment primitive.

With the limits feature, if options.limits sets any cap it is enforced now. When the active mechanism can’t honor a requested limit (no cgroup/Job Object, or a Linux cgroup whose controllers can’t be enabled — see ResourceLimits for the cgroup-v2 real-root requirement) this returns Error::ResourceLimit — rather than handing back an unbounded group — and an invalid cap value returns it too, with LimitReason::Invalid.

Source

pub fn spawn(&self, cmd: Command) -> Result<Child>

Spawn cmd as a member of this group.

The returned Child — and any process it later spawns — belongs to the group and is reaped when the group is killed or dropped. The caller is responsible for configuring cmd’s stdio; the group only handles containment. To build a capture-wired tokio::process::Command from a Command, use its to_tokio_command() bridge (a hidden raw-tokio helper), or construct the tokio::process::Command directly.

Windows: to make containment race-free the child is created CREATE_SUSPENDED, assigned to the job, then resumed. This overwrites any process-creation flags the caller set on cmd (e.g. CREATE_NO_WINDOW) — Win32 exposes no way to read them back and OR the suspend bit in. The Command-driven launch paths (run helpers, start, pipelines) don’t have this limitation: their Command::create_no_window flag travels alongside the OS command and is OR’d in. Only this raw escape hatch forces CREATE_SUSPENDED alone. Unix: the group likewise installs a pre_exec hook on cmd to join the cgroup / process group.

These mutations make cmd single-use: the spawn appends a pre_exec hook (Unix) and re-sets the creation flags (Windows), which would stack if the same command were spawned twice. spawn takes cmd by value so that reuse is a compile error rather than a silent hook-stacking footgun — build a fresh Command per spawn. (The crate’s own run helpers already rebuild the OS command per run, so this only ever concerned direct spawn callers.)

§Errors

Error::Spawn if the OS refuses to start cmd — the working directory is bad, permission is denied, and so on. (This raw path reports every launch failure as Error::Spawn; the Command-driven run helpers, by contrast, translate a not-found program into Error::NotFound.)

Source

pub fn adopt(&self, child: &Child) -> Result<()>

Available on crate feature process-control only.

Attach an already-started Child to this group.

Only the child itself is moved into the group; processes it has already spawned keep their original containment (future forks are captured).

On the POSIX process-group mechanism, a child that has already exec’d cannot be re-grouped (POSIX forbids it), so it is tracked individually: the child itself is signalled/killed with the group, but — unlike on Windows/cgroup — its future forks are not captured. The caller keeps the Child handle and is responsible for reaping: an adopted child that exited but was never awaited probes as alive, so a graceful shutdown can wait out its full timeout on the zombie before escalating.

Reap promptly (pid-reuse hazard). An individually-tracked adopted child is remembered by pid. If you let it exit and be reaped elsewhere without dropping/tearing down this group, that pid can be recycled by the OS to an unrelated process — and this group’s later teardown would then signal that stranger. The crate has no start-time identity to detect the reuse (and macOS’s small pid space makes it likelier). Reap an adopted child through this group’s lifetime, or tear the group down when done, so a stale pid is never carried across a reuse.

On the containment backends, adopting a child that has already exited but not yet been reaped is a successful no-op (Ok) — there is nothing left to contain — while an already-reaped child (one that was waited, so its handle/pid is gone) errors, since there is no longer anything to reference.

§Errors

Error::Io if child has already been reaped (awaited), leaving no live handle/pid to reference. Adopting an exited-but-unreaped child is a successful no-op.

Source

pub fn kill_all(&self) -> Result<()>

Immediately hard-kill every process currently in the group. Idempotent; the group remains usable for further spawns afterwards.

This is an unconditional hard kill (SIGKILL / cgroup.kill / TerminateJobObject), not a graceful SIGTERM — for a SIGTERM → grace → SIGKILL teardown use shutdown / shutdown_ref. The name mirrors the underlying Job::kill_all it delegates to.

On the legacy per-pid kill fallback (a Linux kernel without cgroup.kill, pre-5.14), a tree that won’t drain within the bounded sweep — a fork bomb still out-spawning, or un-reapable D-state zombies — surfaces as an Err rather than a false success; the atomic backends (cgroup.kill, Windows Job Object) don’t need to.

Process-group mechanism (macOS/BSD, Linux process-group fallback). A member that changed its real/saved uid (a sudo/setuid child) and rejects SIGKILL with EPERM while still alive is surfaced as an Err — the containment gap is reported, not hidden. The one EPERM that is not surfaced is the harmless one: on those platforms killpg also returns EPERM for a group whose only member is an unreaped zombie (dead), and the two are indistinguishable from the errno alone, so the target’s actual run state is checked after the EPERM (proc_pidinfo on macOS, the /proc/<pid>/stat state field on the Linux fallback) and only a genuinely-alive, non-zombie member fails the call. On the BSDs, where no process-state reader is wired up, a delivery EPERM stays swallowed (best-effort), so a privileged child can still outlive kill_all there — the atomic mechanisms (cgroup.kill, Job Object) have no such gap.

§Errors

Error::Io in two cases, both on the non-atomic Unix backends: the legacy per-pid kill fallback (a pre-5.14 Linux kernel without cgroup.kill) when the tree won’t drain within the bounded sweep, and the process-group mechanism (macOS/Linux fallback) when a live, non-zombie member rejects SIGKILL with EPERM (a uid-changed child — see above). The atomic backends (cgroup.kill, Windows Job Object) never fail here.

Source

pub fn signal(&self, sig: Signal) -> Result<()>

Available on crate feature process-control only.

Broadcast sig to every process in the group.

Best-effort: a member that has already exited is skipped, and an empty group succeeds trivially.

§Platform support
  • Linux (cgroup or process-group fallback), macOS/BSD — any signal, attempted for every live member of the tree.
  • Windows — only Signal::Kill; any other signal — including Signal::Other — returns Error::Unsupported.

SIGKILL (Signal::Kill, or Other(libc::SIGKILL)) is routed through the same whole-tree hard kill as kill_all on every backend (cgroup.kill / killpg / Job Object terminate), so it cannot miss a process forked mid-broadcast. Other signals are a per-member broadcast.

Limitation (process-group mechanism only). On macOS/BSD and the Linux process-group fallback, delivery failures such as EPERM are not surfaced: this arbitrary-signal broadcast is best-effort and returns Ok. Unlike kill_all — which checks the target’s run state to report a live, non-zombie member that rejects SIGKILLsignal makes no such live/zombie discrimination and always returns Ok on this mechanism, even for Signal::Kill; reach for kill_all if you need a rejected hard kill surfaced. The Linux cgroup mechanism does surface delivery failures for signals other than SIGKILL.

§Errors

Error::Unsupported on Windows for any signal other than Signal::Kill (Job Objects have no POSIX signals). On the Linux cgroup mechanism, Error::Io if the OS rejects delivering the signal to a member. Delivery errors are deliberately not reported by the process-group mechanism (see above).

Source

pub fn suspend(&self) -> Result<()>

Available on crate feature process-control only.

Suspend (freeze) every process in the group.

§Platform support
  • Linux cgroup — one cgroup.freeze write covering the whole subtree (kernel ≥ 5.2; older kernels fall back to per-process SIGSTOP). The freeze is applied by the kernel shortly after the write returns, not instantaneously.
  • Linux process-group fallback, macOS/BSDSIGSTOP to every group; an individually-tracked adopted child (see adopt) is frozen alone — its own descendants keep running.
  • Windows — suspends every thread of every member process. Best-effort and not atomic: threads spawned mid-walk can be missed, and Windows keeps per-thread suspend counts, so nested suspend calls stack — N suspends need N resumes. On Unix suspend/resume are idempotent (level-triggered).

A suspended tree can still be hard-killed (kill_all, or dropping the group) — SIGKILL, cgroup.kill, and TerminateJobObject all act on frozen processes. The graceful shutdown, however, starts with a SIGTERM that a frozen tree cannot act on until thawed, so it waits out shutdown_timeout and then escalates; call resume first for a clean graceful shutdown.

Spawning into a suspended group is platform-divergent. Under the Linux cgroup mechanism the freeze is group state: a child spawned (or adopted) while the group is suspended joins the frozen cgroup and starts frozen — it does not run until resume. Worse, the spawn call itself can block until then: the child joins the cgroup before exec, so it can freeze before the spawn handshake completes and start never returns. The Windows and POSIX process-group mechanisms freeze only the members present at the call, so a later spawn runs normally. Don’t start new work in a suspended group (e.g. a Supervisor::with_runner(&group) restarting into it) — resume first.

On Unix, a graceful shutdown of a suspended group cannot drain (C7): frozen members don’t run their SIGTERM handlers (and a SIGSTOP’d member keeps the signal pending), so the graceful phase burns its full shutdown_timeout and then hard-kills — or, under escalate_to_kill = false, spares the still-frozen survivors. resume before a graceful shutdown if you want the members to actually handle the signal. (On Windows the point is moot: a graceful shutdown is a prompt hard kill regardless — there’s no soft-signal tier and no grace wait — so a suspended group is torn down at once, not after the timeout.)

§Errors

Error::Unsupported if the active mechanism cannot freeze the tree; otherwise Error::Io if the OS rejects the freeze / SIGSTOP.

Source

pub fn resume(&self) -> Result<()>

Available on crate feature process-control only.

Resume a tree suspended by suspend.

See suspend for the platform matrix and the Windows suspend-count nesting caveat.

§Errors

Error::Unsupported if the active mechanism cannot thaw the tree; otherwise Error::Io if the OS rejects the resume / SIGCONT.

Source

pub fn members(&self) -> Result<Vec<u32>>

Available on crate feature process-control only.

The pids of the processes currently in the group.

A point-in-time snapshot: a returned pid may belong to a process that exits (or is reaped) immediately afterwards, and a process spawned during the call may be missing. Useful for diagnostics, dashboards, and targeted per-pid action.

§Platform support
  • Windows — every pid assigned to the Job Object (the whole tree).
  • Linux cgroup — every pid in the cgroup (cgroup.procs, whole tree).
  • Linux process-group fallback, macOS/BSD — the tracked group leaders, plus any individually-tracked adopted child (one pid per spawned/adopted child); descendants inside the groups are contained but not enumerated. An exited child still counts as a member until it is reaped (awaited): the liveness probe sees the not-yet-collected process.
§Errors

Error::Io if the group’s membership cannot be read (e.g. a failed cgroup.procs read or Job Object query).

Source

pub fn members_info(&self) -> Result<Vec<MemberInfo>>

Available on crate feature process-control only.

An enriched, point-in-time snapshot of the group’s members — the same set as members, but each pid carried in a MemberInfo alongside best-effort parent pid, image name, and start time.

The metadata-carrying companion to members: use it for diagnostics that want more than bare pids (a members_snapshot event, a process tree view). Which processes appear is identical to members — see its platform matrix — and each enriching field is None wherever the platform can’t report it, never a fabricated value (full per-field matrix on MemberInfo).

§Platform support
  • Windows — the whole tree (every pid in the Job Object); ppid and image name from one Toolhelp32 process snapshot, start time (creation FILETIME) per pid.
  • Linux cgroup — the whole tree (cgroup.procs); ppid, comm image name, and start time from one /proc/<pid>/stat read each.
  • Linux process-group fallback — the tracked group leaders (as members), enriched from /proc the same way.
  • macOS — the tracked leaders; ppid / image name / start time via proc_pidinfo.
  • the BSDs — the tracked leaders with every enriching field None (no wired-up per-process reader — see MemberInfo::start_time); the pid is still reported, which is a correct result, not an error.
§Racing a member that exits

A point-in-time snapshot taken per pid: if a member exits between its pid being enumerated and its metadata being read, that pid is skipped (omitted from the Vec) rather than reported with fabricated fields — one vanished member never fails the whole call. A member that is still present but for which only some finer field can’t be read (e.g. its start-time handle just closed) is kept, with that field None.

§No command line

The raw argv / environment is deliberately never included, on any platform — a command line routinely carries secrets, and redaction is the consumer’s policy to own (the crate’s standing “never argv/env” stance).

§Errors

Error::Io only if the group’s membership cannot be read (the same failure as members — a failed cgroup.procs read or Job Object query) or, on Windows, if the process-metadata snapshot cannot be created at all. A single member vanishing is not an error (it is skipped).

Source

pub async fn shutdown(self) -> Result<()>

Gracefully tear the group down, consuming it.

On Unix: SIGTERM the tree, wait up to shutdown_timeout, then SIGKILL survivors when escalate_to_kill is set. On Windows the kill is atomic. Dropping the group instead (without calling this) performs only the hard kill.

Reap your children, or the grace is wasted (POSIX process-group mechanism only). On the Mechanism::ProcessGroup fallback (macOS/the BSDs, and Linux without a usable cgroup), liveness is probed by signalling the group id, and an unreaped zombie still answers — its process-group entry survives until the child is waited. So a child that exits promptly on SIGTERM but whose RunningProcess handle was dropped without being awaited (or is still held un-awaited) reads as alive for the full shutdown_timeout, and shutdown then burns the whole grace plus a pointless SIGKILL escalation. Await each child you start into the group (any consuming verb, or wait) so its handle reaps it. The Windows Job Object and Linux cgroup mechanisms are immune (a process leaves cgroup.procs / the job on exit, before reaping).

When escalate_to_kill is set, the final hard kill can surface the same errors as kill_all: the undrained-tree Err on the legacy pre-5.14 per-pid fallback, and — on the process-group mechanism — a live, non-zombie member that rejects SIGKILL with EPERM (a uid-changed child). A harmless zombie-only group is not reported (see kill_all).

Holding the group behind a shared handle (an Arc, a long-lived supervisor) that can’t be moved out by value? Use the borrowing twin shutdown_ref — same teardown, &self.

§Errors

Error::Io if the graceful teardown fails — including, when escalate_to_kill performs the final hard kill, the same failures as kill_all: the undrained-tree failure on the legacy pre-5.14 per-pid fallback, and a process-group member that rejects SIGKILL with EPERM while still alive.

Source

pub async fn shutdown_ref(&self) -> Result<()>

Gracefully tear the group down without consuming it — the borrowing twin of shutdown, for a group held behind a shared handle (an Arc, a supervisor) that cannot be moved out by value to call the consuming form.

Identical teardown to shutdown: on Unix, SIGTERM the tree, wait up to the configured shutdown_timeout, then SIGKILL survivors when escalate_to_kill is set; on Windows the kill is atomic and the timeout is ignored. The group stays usable afterwards (a re-shutdown_ref on an already-drained tree is a near no-op). Spawning or adopting a new child re-arms Drop’s kill backstop for the whole group, so a straggler started after — or concurrently with — this shutdown is still torn down on Drop: a non-escalating shutdown that is still in flight when the child joins cannot silently strip the newcomer of its backstop (its spare is keyed to a generation the join bumps). A group left untouched keeps the survivors an escalate_to_kill = false shutdown chose to spare.

The same reaping caveat as shutdown applies on the POSIX process-group mechanism: await each child you started into the group, or an unreaped zombie reads as alive for the whole grace.

§Errors

Error::Io if the graceful teardown fails (see shutdown — the same undrained-tree failure on the legacy per-pid fallback and the process-group live-EPERM on the final hard kill apply).

Source

pub fn stats(&self) -> Result<ProcessGroupStats>

Available on crate feature stats only.

Snapshot the group’s resource usage (active process count and, where the platform supports it, total CPU time and peak memory). See ProcessGroupStats.

§Errors

Error::Io if the platform’s resource query fails.

Source

pub fn sample_stats(&self, every: Duration) -> StatsSampler<'_>

Available on crate feature stats only.

Sample stats on an interval as a Stream of snapshots. The first sample is taken immediately; the series ends on the first failure. A zero every is clamped to 1 ms.

Source

pub fn mechanism(&self) -> Mechanism

The containment mechanism actually in effect (see Mechanism).

Source§

impl ProcessGroup

Source

pub async fn start(&self, command: &Command) -> Result<RunningProcess>

Start command as a member of this (shared) group and return a live handle. The handle does not own the group, so dropping it leaves the group and any sibling processes intact — the caller controls teardown.

§Errors

The launch surface: Error::NotFound / Error::Spawn (locate/start failure), Error::Unsupported (a POSIX-only primitive unavailable on this platform), Error::Cancelled (a pre-cancelled token), or Error::Io (e.g. a one-shot stdin source already consumed). Unlike JobRunner::start, no new group is created here — the child joins this existing group.

Trait Implementations§

Source§

impl Debug for ProcessGroup

Source§

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

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

impl ProcessRunner for ProcessGroup

Source§

fn output_string<'life0, 'life1, 'async_trait>( &'life0 self, command: &'life1 Command, ) -> Pin<Box<dyn Future<Output = Result<ProcessResult<String>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Run command to completion, capturing stdout/stderr and the exit code. A non-zero exit is reported in the result, not raised.
Source§

fn start<'life0, 'life1, 'async_trait>( &'life0 self, command: &'life1 Command, ) -> Pin<Box<dyn Future<Output = Result<RunningProcess>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Start command and return a live RunningProcess for streaming, readiness probes, or incremental consumption. Read more
Source§

fn output_bytes<'life0, 'life1, 'async_trait>( &'life0 self, command: &'life1 Command, ) -> Pin<Box<dyn Future<Output = Result<ProcessResult<Vec<u8>>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Run command to completion, capturing stdout as raw bytes (output_string captures it as lossy-UTF-8 text); stderr is still text. For binary tools — git cat-file, tar -c, an image transcoder — whose stdout is not UTF-8. Read more

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
Source§

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

Source§

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

Source§

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

Source§

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

Source§

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

Source§

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

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> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

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

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

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> ProcessRunnerExt for T
where T: ProcessRunner + ?Sized,

Source§

fn run<'life0, 'life1, 'async_trait>( &'life0 self, command: &'life1 Command, ) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'async_trait>>
where Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Run, require an accepted exit, and return trimmed stdout. Accepted is 0 by default, widened by Command::ok_codes; any other code is Error::Exit.
Source§

fn run_unit<'life0, 'life1, 'async_trait>( &'life0 self, command: &'life1 Command, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Run for the side effect: require an accepted exit (0, or any code in Command::ok_codes), discard the output.
Source§

fn exit_code<'life0, 'life1, 'async_trait>( &'life0 self, command: &'life1 Command, ) -> Pin<Box<dyn Future<Output = Result<i32>> + Send + 'async_trait>>
where Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Run and return just the exit code. A run that produced no code surfaces as an error — a timeout as Error::Timeout, a signal-kill as Error::Signalled — rather than a synthetic sentinel, mirroring ensure_success.
Source§

fn probe<'life0, 'life1, 'async_trait>( &'life0 self, command: &'life1 Command, ) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>
where Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Run a predicate command and read its exit code as a boolean: exit 0Ok(true), exit 1Ok(false), anything else → Err (other code as Error::Exit, timeout as Error::Timeout, signal-kill as Error::Signalled). For commands whose exit code is the answer — git diff --quiet, grep -q, …
Source§

fn checked<'life0, 'life1, 'async_trait>( &'life0 self, command: &'life1 Command, ) -> Pin<Box<dyn Future<Output = Result<ProcessResult<String>>> + Send + 'async_trait>>
where Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Run, require an accepted exit (0 by default, widened by Command::ok_codes), and return the full captured result (untrimmed stdout). The building block for the parse/try_parse helpers — use it when you need the whole ProcessResult after success-checking, rather than just trimmed stdout (run) or the raw result (output_string). Read more
Source§

fn parse<'life0, 'life1, 'async_trait, T, F>( &'life0 self, command: &'life1 Command, parse: F, ) -> Pin<Box<dyn Future<Output = Result<T>> + Send + 'async_trait>>
where T: Send + 'async_trait, F: FnOnce(&str) -> T + Send + 'async_trait, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Run (requiring an accepted exit) and feed the captured stdout to an infallible parse closure — the shape of struct-returning CLI commands (git/jj --format output). Built on checked, but unlike it, fails loud on a bounded-buffer truncation so the parser never silently sees a clipped tail; returns the parsed value. Read more
Source§

fn try_parse<'life0, 'life1, 'async_trait, T, F>( &'life0 self, command: &'life1 Command, parse: F, ) -> Pin<Box<dyn Future<Output = Result<T>> + Send + 'async_trait>>
where T: Send + 'async_trait, F: FnOnce(&str) -> Result<T> + Send + 'async_trait, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Run (requiring an accepted exit) and feed the captured stdout to a fallible parse closure — the shape of JSON deserialization, where a parse failure becomes Error::Parse (or whatever error the closure returns). Like parse it is built on checked, fails loud on truncation, and — being generic over F — cannot be dispatched through a dyn ProcessRunnerExt object (the trait isn’t object-safe), though it is callable on a &dyn ProcessRunner. The Command::try_parse / CliClient::try_parse wrappers are the ergonomic path.
Source§

fn first_line<'life0, 'life1, 'async_trait, F>( &'life0 self, command: &'life1 Command, predicate: F, ) -> Pin<Box<dyn Future<Output = Result<Option<String>>> + Send + 'async_trait>>
where F: Fn(&str) -> bool + Send + 'async_trait, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Stream command’s stdout and return the first line matching predicate (None if the stream ends first), bounded by the command’s timeout: a Some deadline surfaces as Error::Timeout and tears the process down. On an own-group runner (JobRunner, the default) that teardown covers the whole tree; on a shared ProcessGroup it reaches the run’s direct child by pid — a forking child’s grandchildren (and, on the Linux cgroup mechanism, a direct child that catches the graceful signal and closes stdout but keeps running) may outlive the probe until the group is dropped. Bound such a run with a whole-chain owner instead. 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.
Source§

impl<T> WithSubscriber for T

Source§

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
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

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