From 9e944a7077bb5873a8dc68b0f443ddc112a37a90 Mon Sep 17 00:00:00 2001 From: Sascha Grunert Date: Tue, 10 Sep 2024 13:01:45 +0200 Subject: [PATCH] Run waitpid on childs to ensure no zombies are left behind Fixes https://github.com/containers/crun/issues/1482 Signed-off-by: Sascha Grunert --- conmon-rs/server/src/child_reaper.rs | 33 +++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/conmon-rs/server/src/child_reaper.rs b/conmon-rs/server/src/child_reaper.rs index 057eeca80f..f48c90f399 100644 --- a/conmon-rs/server/src/child_reaper.rs +++ b/conmon-rs/server/src/child_reaper.rs @@ -13,7 +13,7 @@ use nix::{ errno::Errno, sys::{ signal::{kill, Signal}, - wait::{waitpid, WaitStatus}, + wait::{waitpid, WaitPidFlag, WaitStatus}, }, unistd::{getpgid, Pid}, }; @@ -137,6 +137,9 @@ impl ChildReaper { // meaning there is no other entity that could cancel the read_loops. token.cancel(); + // Wait to ensure that all children do not become zombies. + Self::check_child_processes(); + bail!(err_str) } @@ -149,6 +152,34 @@ impl ChildReaper { Ok((grandchild_pid, token)) } + fn check_child_processes() { + debug!("Checking child processes"); + let pid = Pid::from_raw(-1); + loop { + match waitpid(pid, WaitPidFlag::WNOHANG.into()) { + Ok(WaitStatus::Exited(p, code)) => { + debug!("PID {p} exited with status: {code}"); + break; + } + Ok(WaitStatus::StillAlive) => { + debug!("PID {pid} is still in same state"); + break; + } + Ok(_) => { + continue; + } + Err(Errno::EINTR) => { + debug!("Retrying on EINTR for PID {pid}"); + continue; + } + Err(err) => { + error!("Unable to waitpid on {:#}", err); + break; + } + }; + } + } + pub fn watch_grandchild( &self, child: Child,