Skip to main content

ReapableChild

Struct ReapableChild 

Source
pub(crate) struct ReapableChild {
    seq: u64,
    pid: Pid,
    process: Arc<Process>,
    reaped: Arc<AtomicBool>,
    io: Option<Arc<ContainerIO>>,
    token: CancellationToken,
}
Expand description

A registered child, until its watcher ended. What only the watcher needs moves into it, see ExitHandling.

Fields§

§seq: u64

Tells the registrations apart, unlike the PID, which gets reused.

§pid: Pid§process: Arc<Process>

Opened at the registration, before the watcher could reap the child. The watcher reaps it before it cancels the token, or after that for one killed at its timeout. Once it got reaped, the PID may belong to another process, which the signals through the pidfd do not reach. Kernels without pidfds (before 5.3) only get the check of the PID, see Process::open.

§reaped: Arc<AtomicBool>

Set once the watcher reaped the child. It stays registered while the watcher finishes its output, its PID may belong to another child by then, which the registration must not claim, see ChildReaper::is_claimed.

§io: Option<Arc<ContainerIO>>

The stdio of a container, which container level operations use, see ChildReaper::get. None for an exec, only its consumer holds its stdio, which also tells the kinds apart. One killed at its timeout stays registered until it got reaped, which may take until the server stops, but its pipes or its terminal get released with the consumer.

§token: CancellationToken

Implementations§

Source§

impl ReapableChild

Source

pub(super) async fn handle_oom( event: Option<OOMEvent>, exit_code: i32, oom_exit_paths: &[PathBuf], ) -> bool

Whether the process which exited with exit_code got OOM killed. The watcher writes the files for the OOMs it could tell on its own, this the ones which only the exit status tells.

Source

pub(super) async fn wait_for_output( attach: SharedContainerAttach, deadline: Instant, ) -> bool

Wait until the output ended, or until the Drain gives up. A process which inherited the pipes and keeps them open must not delay the exit file. Output on its way into the log is no pause, a slow log driver must not cut off the end of the log, up to the deadline. False if the deadline passed, which got logged here.

Source

pub(super) async fn finish_output( attach: SharedContainerAttach, logger: &Arc<Mutex<ContainerLog>>, )

Wait for the output like ReapableChild::wait_for_output, then stop the read loops and wait for them to end, which writes the lines still waiting for their ending into the log, and sync the log to disk. Nothing reaches the log after the exit file this way. A log write or sync which hangs must not hold the exit file back, all of it takes DRAIN_MAX_LOG_WAIT at most.

Source

pub(crate) fn from_child(child: Child) -> (Box<str>, Self, ExitHandling)

Split the child into the registered part and what only its watcher needs.

Source

async fn wait_or_kill( process: &Process, wait: Pin<&mut impl Future<Output = i32>>, timeout: Option<Instant>, ) -> (i32, bool)

Wait for the exit of the process with wait, or kill it at the timeout, and return its exit code and whether it timed out. The wait stays pending on the timeout, the watcher reaps the process with it once the exit went out, see ReapableChild::reap_killed.

Source

async fn reap_killed(wait: Pin<&mut impl Future<Output = i32>>)

Reap the process which got killed at its timeout through the wait which timed out, once the SIGKILL took effect. A second wait would register the pidfd again, or race this one, whose blocking wait still runs without a pidfd, and could take the exit of another child which reused the PID. A process stuck in the kernel, like on a hung network mount, may take long, it keeps only a pidfd busy meanwhile, not a thread. The process stays registered until then, so that the orphan sweep leaves it to this wait and the shutdown waits for it and reports it if it does not exit in time.

Source

pub(super) fn watch( &self, exit: ExitHandling, forget: impl FnOnce() + Send + 'static, ) -> Receiver<ExitChannelData>

Watch the process and return the receiver for its exit, which exists before the task starts, a receiver subscribed after the exit would miss it. forget runs once the exit got sent and the process got reaped, which comes later for one killed at its timeout, or the task ended otherwise, like with a panic. A task which never ran, which tokio drops right in spawn while the runtime shuts down, does not run it, so the caller may hold a lock which forget takes.

Source

async fn write_to_exit_paths(code: i32, paths: &[PathBuf])

Write the exit code to every exit path. Failures are logged per path, one unwritable path must not prevent the others.

Source

pub(super) async fn write_exit_file(path: &Path, contents: &str) -> Result<()>

Write the exit file at once, like conmon does. CRI-O reads it as soon as it gets created, which must not find it empty. CRI-O ignores the temporary file, which is not named like a container. A symlink in its place does not get followed, like for the log files, the file gets created new.

Source

async fn write_new_file(path: &Path, contents: &str) -> Result<()>

Create the file new with the contents. One left behind at the path, like by a crash, gets removed first, a symlink is not followed.

Source§

impl ReapableChild

Source

pub(crate) fn pid(&self) -> Pid

The PID of the child.

Source

fn claimed_pid(&self) -> Option<Pid>

The PID of the child while its watcher still waits for it, see Self::reaped.

Source

fn is_container(&self) -> bool

Whether the child is a container, not an exec, see Self::io.

Source

pub(crate) fn container(&self) -> Option<RegisteredContainer>

The container, none for an exec.

Trait Implementations§

Source§

impl Clone for ReapableChild

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for ReapableChild

Source§

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

Formats the value using the given formatter. 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> 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
§

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

§

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

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
§

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.

§

impl<T> IntoRequest<T> for T

§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
§

impl<L> LayerExt<L> for L

§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in [Layered].
§

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

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 = !

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

fn try_from(value: U) -> Result<T, !>

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