use std::marker::PhantomData;
use libc::pid_t;
use nix::sys::wait::{waitpid};
use nix::sys::wait::WaitPidFlag;
use nix::errno::Errno::{EINTR, ECHILD};
use nix::Error;
use {ExitStatus, Signal};
pub struct ZombieIterator(PhantomData<u8>);
impl Iterator for ZombieIterator {
type Item = (pid_t, ExitStatus);
fn next(&mut self) -> Option<(pid_t, ExitStatus)> {
use nix::sys::wait::WaitStatus::*;
loop {
match waitpid(None, Some(WaitPidFlag::WNOHANG)) {
Ok(PtraceEvent(..)) => {}
Ok(PtraceSyscall(..)) => {}
Ok(Exited(pid, status)) => {
return Some((pid.into(), ExitStatus::Exited(status as i8)));
}
Ok(Signaled(pid, sig, core)) => {
return Some((pid.into(), ExitStatus::Signaled(sig, core)));
}
Ok(Stopped(_, _)) => continue,
Ok(Continued(_)) => continue,
Ok(StillAlive) => return None,
Err(Error::Sys(EINTR)) => continue,
Err(Error::Sys(ECHILD)) => return None,
Err(e) => {
panic!("Unexpected waitpid error: {:?}", e);
}
}
}
}
}
pub fn reap_zombies() -> ZombieIterator { ZombieIterator(PhantomData) }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ChildEvent {
Death(pid_t, ExitStatus),
Stop(pid_t, Signal),
Continue(pid_t),
}
pub struct ChildEventsIterator(PhantomData<u8>);
impl Iterator for ChildEventsIterator {
type Item = ChildEvent;
fn next(&mut self) -> Option<ChildEvent> {
use self::ChildEvent::*;
use nix::sys::wait::WaitStatus::*;
let flags = WaitPidFlag::WNOHANG | WaitPidFlag::WUNTRACED |
WaitPidFlag::WCONTINUED;
loop {
match waitpid(None, Some(flags)) {
Ok(PtraceEvent(..)) => {}
Ok(PtraceSyscall(..)) => {}
Ok(Exited(pid, status)) => {
return Some(Death(pid.into(),
ExitStatus::Exited(status as i8)));
}
Ok(Signaled(pid, sig, core)) => {
return Some(Death(pid.into(),
ExitStatus::Signaled(sig, core)));
}
Ok(Stopped(pid, sig)) => return Some(Stop(pid.into(), sig)),
Ok(Continued(pid)) => return Some(Continue(pid.into())),
Ok(StillAlive) => return None,
Err(Error::Sys(EINTR)) => continue,
Err(Error::Sys(ECHILD)) => return None,
Err(e) => {
panic!("Unexpected waitpid error: {:?}", e);
}
}
}
}
}
pub fn child_events() -> ChildEventsIterator {
ChildEventsIterator(PhantomData)
}