use std::io;
use std::os::fd::{FromRawFd, OwnedFd, RawFd};
use tokio::io::unix::AsyncFd;
use crate::failure::{Doing, Failure};
pub(super) struct Watch(AsyncFd<OwnedFd>);
impl Watch {
pub(super) fn process(pid: libc::pid_t) -> Result<Self, Failure> {
let raw = unsafe { libc::syscall(libc::SYS_pidfd_open, pid, 0) };
if raw < 0 {
return Err(io::Error::last_os_error()).doing(|| format!("watching bash {pid}"));
}
Self::over(unsafe { OwnedFd::from_raw_fd(raw as RawFd) })
}
pub(super) fn held(handle: OwnedFd) -> Result<Self, Failure> {
Self::over(handle)
}
fn over(fd: OwnedFd) -> Result<Self, Failure> {
AsyncFd::new(fd)
.map(Self)
.doing(|| "registering the watch".into())
}
pub(super) async fn fired(&self) -> Result<(), Failure> {
self.0
.readable()
.await
.map(|_| ())
.doing(|| "waiting for the end".into())
}
}