diff --git a/test_bin/main.rs b/test_bin/main.rs index d15425064..8957b0037 100644 --- a/test_bin/main.rs +++ b/test_bin/main.rs @@ -1,5 +1,25 @@ // Does nothing and just exits after waiting for 30 seconds. +use std::process::{Child, Command}; + +fn maybe_start_child(last: String, args: &[String]) -> Option { + if last == "1" { + let mut cmd = Command::new(&args[0]); + for arg in &args[1..] { + cmd.arg(arg); + } + Some(cmd.spawn().expect("failed to run command")) + } else { + None + } +} + fn main() { - std::thread::sleep(std::time::Duration::from_secs(30)); + let mut args: Vec = std::env::args().collect(); + let child = args.pop().and_then(|last| maybe_start_child(last, &args)); + if child.is_some() { + std::thread::sleep(std::time::Duration::from_secs(3)); + } else { + std::thread::sleep(std::time::Duration::from_secs(30)); + } } diff --git a/tests/process.rs b/tests/process.rs index 132f8dc78..b335933c3 100644 --- a/tests/process.rs +++ b/tests/process.rs @@ -801,3 +801,50 @@ fn test_process_run_time() { run_time ); } + +// Test that if the parent of a process is removed, then the child PID will be +// updated as well. +#[test] +fn test_parent_change() { + if !sysinfo::IS_SUPPORTED_SYSTEM || cfg!(feature = "apple-sandbox") { + return; + } + + build_test_binary(); + let mut p = std::process::Command::new("./target/test_binary") + .arg("1") + .spawn() + .unwrap(); + + std::thread::sleep(std::time::Duration::from_secs(1)); + + let pid = Pid::from_u32(p.id() as _); + let mut s = System::new(); + s.refresh_processes(); + + assert_eq!( + s.process(pid).expect("process was not created").parent(), + sysinfo::get_current_pid().ok(), + ); + + let child_pid = s + .processes() + .iter() + .find(|(_, proc_)| proc_.parent() == Some(pid)) + .map(|(pid, _)| *pid) + .expect("failed to get child process"); + + // Waiting for the parent process to stop. + p.wait().expect("wait failed"); + + s.refresh_processes(); + // Parent should not be around anymore. + assert!(s.process(pid).is_none()); + + let child = s.process(child_pid).expect("child is dead"); + // Child should have a different parent now. + assert_eq!(child.parent(), None); + + // We kill the child to clean up. + child.kill(); +}