use std::io;
use std::os::fd::AsRawFd;
use std::os::fd::FromRawFd;
use std::os::fd::OwnedFd;
use nix::errno::Errno;
use nix::libc;
pub struct PidFd {
fd: OwnedFd,
}
impl PidFd {
pub fn open(pid: u64) -> io::Result<PidFd> {
let ret = unsafe { libc::syscall(libc::SYS_pidfd_open, pid as libc::pid_t, 0_u32) };
if ret < 0 {
Err(io::Error::last_os_error())
} else {
Ok(PidFd {
fd: unsafe { OwnedFd::from_raw_fd(ret as i32) },
})
}
}
pub fn wait_status(&self) -> Result<i32, Errno> {
let mut siginfo: libc::siginfo_t = unsafe { std::mem::zeroed() };
let ret = unsafe {
libc::waitid(
libc::P_PIDFD,
self.fd.as_raw_fd() as libc::id_t,
&mut siginfo,
libc::WEXITED,
)
};
if ret < 0 {
return Err(Errno::last());
}
let code = siginfo.si_code;
let status = unsafe { siginfo.si_status() };
let wait_status = match code {
libc::CLD_EXITED => (status & 0xff) << 8,
libc::CLD_KILLED => status & 0x7f,
libc::CLD_DUMPED => (status & 0x7f) | 0x80,
_ => 0,
};
Ok(wait_status)
}
}
impl AsRawFd for PidFd {
fn as_raw_fd(&self) -> i32 {
self.fd.as_raw_fd()
}
}