Skip to main content

Running

Struct Running 

Source
pub struct Running<'obs> { /* private fields */ }
Expand description

A running sandbox.

Returned by Cage::spawn and Cage::spawn_with once the command is executing. The handle owns the caller side of the sandbox’s channels: waiting pumps captured output to the observer and collects the command’s exit status, terminate requests a graceful stop, and kill forcibly tears the sandbox down.

Waiting is fused: once the outcome is known, every further wait returns it without blocking.

Dropping the handle without waiting neither kills the sandbox (unless stop_with_caller is set, whose tie the drop severs) nor collects its outcome; without a PID namespace the supervisor process then remains a zombie child process of the caller until the caller exits. Prefer waiting — including after a kill.

The escalation recipe, for callers that need a bounded stop:

let mut running = cage.spawn()?;
let status = match running.wait_deadline(soft)? {
    Some(status) => status,
    None => {
        running.terminate()?; // SIGTERM: a chance to exit cleanly
        match running.wait_deadline(hard)? {
            Some(status) => status,
            None => {
                running.kill()?; // SIGKILL: tear the sandbox down
                running.wait()?
            }
        }
    }
};

Implementations§

Source§

impl<'obs> Running<'obs>

Source

pub fn pid(&self) -> u32

The host process id of the sandbox supervisor — the process this handle anchors on: the namespace init, or the command process itself without a PID namespace. Not the launch stage, which built the namespaces and, with a PID namespace, has already exited.

Informational — for signaling, use kill and terminate, which cannot hit a recycled pid.

Source

pub fn wait(&mut self) -> Result<ExitStatus, Error>

Waits for the command to terminate, pumping captured output to the observer, and returns its exit status.

Like Cage::run, a non-zero exit is data, not an error. An error means the library failed to collect the outcome.

When output is captured, the wait completes once the command’s outcome is known and both captured streams have reached end-of-file. Under the default PID namespace, teardown at command exit closes the streams promptly. With pid_namespace(false), a descendant that outlives the command holds the streams open, and an unbounded wait blocks until the last holder closes them; a caller whose command may leave such descendants behind should prefer wait_deadline or wait_timeout.

Source

pub fn wait_deadline( &mut self, deadline: Instant, ) -> Result<Option<ExitStatus>, Error>

Waits until the command terminates or the deadline passes.

Returns Ok(None) when the deadline passes first; the command keeps running, output produced before the deadline has been delivered, and the wait can be resumed. The deadline does not kill anything — escalation is the caller’s, per the recipe above.

Source

pub fn wait_timeout( &mut self, timeout: Duration, ) -> Result<Option<ExitStatus>, Error>

wait_deadline with a relative timeout.

Source

pub fn terminate(&mut self) -> Result<(), Error>

Requests graceful termination: SIGTERM to the command.

The signal is deliverable and trappable, docker-stop style; a command may clean up and exit, or may ignore it. Follow with a deadline and kill for a bounded stop. Requesting termination of a sandbox that has already exited is not an error.

Source

pub fn kill(&mut self) -> Result<(), Error>

Kills the sandbox: SIGKILL to the supervisor.

With a PID namespace this kills its init, and the kernel then kills every process in the namespace — nothing survives. Without one, only the command process itself is killed; descendants it spawned are beyond the library’s reach.

The kill is delivered through a pidfd and cannot hit a recycled pid. Killing a sandbox that has already exited is not an error. After a kill, wait still pumps the output produced before the kill and then reports the outcome.

The killed outcome is reported as signaled(SIGKILL) only once the signal is known delivered; the flag that carries that fact is set after the signal so a failed signal cannot fabricate a killed outcome. When a KillHandle on another thread issues the kill while this thread is waiting, that ordering leaves a narrow window in which the waiter can observe the supervisor’s death before the flag is set and report Error::SupervisorLost instead of signaled(SIGKILL). The kill still took effect; only the reported form differs, and only for a cross-thread kill racing the wait. A same-thread kill (this method before a subsequent wait) is not affected.

Source

pub fn kill_handle(&self) -> Result<KillHandle, Error>

Returns a handle that can terminate or kill the sandbox from another thread, while this handle blocks in a wait.

Trait Implementations§

Source§

impl Debug for Running<'_>

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'obs> !RefUnwindSafe for Running<'obs>

§

impl<'obs> !Send for Running<'obs>

§

impl<'obs> !Sync for Running<'obs>

§

impl<'obs> !UnwindSafe for Running<'obs>

§

impl<'obs> Freeze for Running<'obs>

§

impl<'obs> Unpin for Running<'obs>

§

impl<'obs> UnsafeUnpin for Running<'obs>

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> 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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
Source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
Source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

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

Source§

type Error = !

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<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V