diff --git a/local/recipes/system/driver-manager/source/src/reaper.rs b/local/recipes/system/driver-manager/source/src/reaper.rs index 133a94a266..42971d72ae 100644 --- a/local/recipes/system/driver-manager/source/src/reaper.rs +++ b/local/recipes/system/driver-manager/source/src/reaper.rs @@ -21,6 +21,11 @@ use std::time::Duration; static REAP_FLAG: AtomicBool = AtomicBool::new(false); +#[cfg(test)] +const TEST_NO_EXIT: bool = true; +#[cfg(not(test))] +const TEST_NO_EXIT: bool = false; + extern "C" fn sigchld_handler(_sig: i32) { REAP_FLAG.store(true, Ordering::SeqCst); } @@ -38,7 +43,7 @@ pub fn set_reap_flag() { /// `spawned` map). pub fn spawn_reaper_thread(on_reap: F) -> thread::JoinHandle<()> where - F: Fn(u32) + Send + 'static, + F: Fn(u32, i32) + Send + 'static, { unsafe { libc::signal(libc::SIGCHLD, sigchld_handler as *const () as libc::sighandler_t); @@ -93,6 +98,12 @@ fn run_watchdog(handle: thread::JoinHandle<()>) { ); } } + if !TEST_NO_EXIT { + log::error!("driver-manager-sigchld: reaper unrecoverable; exiting driver-manager for init respawn"); + std::process::exit(1); + } else { + log::warn!("driver-manager-sigchld: reaper exited (test mode, no process exit)"); + } return; } } @@ -118,7 +129,7 @@ fn panic_payload_to_string(payload: &Box) -> String { } } -fn run(on_reap: F) { +fn run(on_reap: F) { log::info!("sigchld-reaper: worker started"); loop { std::thread::sleep(Duration::from_millis(100)); @@ -130,12 +141,13 @@ fn run(on_reap: F) { // for a child so the call will not return success for a // non-zombie pid. We loop until ECHILD. loop { - let res = unsafe { libc::waitpid(-1, std::ptr::null_mut(), libc::WNOHANG) }; + let mut status: i32 = 0; + let res = unsafe { libc::waitpid(-1, &mut status, libc::WNOHANG) }; if res <= 0 { break; } - log::info!("sigchld-reaper: reaped pid {}", res); - on_reap(res as u32); + log::info!("sigchld-reaper: reaped pid {} status 0x{:x}", res, status as u32); + on_reap(res as u32, status); } } } @@ -158,7 +170,7 @@ mod tests { fn reaper_thread_fires_on_flag() { let seen: std::sync::Arc = std::sync::Arc::new(AtomicU32::new(0)); let s = seen.clone(); - let handle = spawn_reaper_thread(move |pid| { + let handle = spawn_reaper_thread(move |pid: u32, _status: i32| { // The worker reads the flag, calls waitpid, and invokes // this on every reaped pid. In the test environment we // cannot have an actual child to reap, so the loop will