diff --git a/src/process/mod.rs b/src/process/mod.rs index 952ec6ad..64874d3c 100644 --- a/src/process/mod.rs +++ b/src/process/mod.rs @@ -833,8 +833,14 @@ impl Process { } /// Is this process still alive? + /// + /// Processes in the Zombie or Dead state are not considered alive. pub fn is_alive(&self) -> bool { - rustix::fs::statat(&self.fd, "stat", AtFlags::empty()).is_ok() + if let Ok(stat) = self.stat() { + stat.state != 'Z' && stat.state != 'X' + } else { + false + } } /// What user owns this process? diff --git a/src/process/tests.rs b/src/process/tests.rs index ce0aa9f0..8309438c 100644 --- a/src/process/tests.rs +++ b/src/process/tests.rs @@ -204,6 +204,25 @@ fn test_smaps() { fn test_proc_alive() { let myself = Process::myself().unwrap(); assert!(myself.is_alive()); + + // zombies should not be considered alive + let mut command = std::process::Command::new("sleep"); + command + .arg("0") + .stdout(std::process::Stdio::null()) + .stderr(std::process::Stdio::null()); + let mut child = command.spawn().unwrap(); + let child_pid = child.id() as i32; + + // sleep very briefly to allow the child to start and then exit + std::thread::sleep(std::time::Duration::from_millis(20)); + + let child_proc = Process::new(child_pid).unwrap(); + assert!(!child_proc.is_alive(), "Child state is: {:?}", child_proc.stat()); + assert!(child_proc.stat().unwrap().state().unwrap() == ProcState::Zombie); + child.wait().unwrap(); + assert!(Process::new(child_pid).is_err()); + assert!(!child_proc.is_alive(), "Child state is: {:?}", child_proc.stat()); } #[test]