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: u64Tells 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: CancellationTokenImplementations§
Source§impl ReapableChild
impl ReapableChild
Sourcepub(super) async fn handle_oom(
event: Option<OOMEvent>,
exit_code: i32,
oom_exit_paths: &[PathBuf],
) -> bool
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.
Sourcepub(super) async fn wait_for_output(
attach: SharedContainerAttach,
deadline: Instant,
) -> bool
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.
Sourcepub(super) async fn finish_output(
attach: SharedContainerAttach,
logger: &Arc<Mutex<ContainerLog>>,
)
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.
Sourcepub(crate) fn from_child(child: Child) -> (Box<str>, Self, ExitHandling)
pub(crate) fn from_child(child: Child) -> (Box<str>, Self, ExitHandling)
Split the child into the registered part and what only its watcher needs.
Sourceasync fn wait_or_kill(
process: &Process,
wait: Pin<&mut impl Future<Output = i32>>,
timeout: Option<Instant>,
) -> (i32, bool)
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.
Sourceasync fn reap_killed(wait: Pin<&mut impl Future<Output = i32>>)
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.
Sourcepub(super) fn watch(
&self,
exit: ExitHandling,
forget: impl FnOnce() + Send + 'static,
) -> Receiver<ExitChannelData>
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.
Sourceasync fn write_to_exit_paths(code: i32, paths: &[PathBuf])
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.
Sourcepub(super) async fn write_exit_file(path: &Path, contents: &str) -> Result<()>
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§impl ReapableChild
impl ReapableChild
Sourcefn claimed_pid(&self) -> Option<Pid>
fn claimed_pid(&self) -> Option<Pid>
The PID of the child while its watcher still waits for it, see
Self::reaped.
Sourcefn is_container(&self) -> bool
fn is_container(&self) -> bool
Whether the child is a container, not an exec, see Self::io.
Sourcepub(crate) fn container(&self) -> Option<RegisteredContainer>
pub(crate) fn container(&self) -> Option<RegisteredContainer>
The container, none for an exec.
Trait Implementations§
Source§impl Clone for ReapableChild
impl Clone for ReapableChild
Auto Trait Implementations§
impl !RefUnwindSafe for ReapableChild
impl !UnwindSafe for ReapableChild
impl Freeze for ReapableChild
impl Send for ReapableChild
impl Sync for ReapableChild
impl Unpin for ReapableChild
impl UnsafeUnpin for ReapableChild
Blanket Implementations§
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
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> ⓘ
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
§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].