use std::{
env,
io::{PipeWriter, Write},
os::fd::{FromRawFd, RawFd},
};
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Not running under procdog supervisor")]
Unsupervised,
#[error("procdog file descriptor number invalid")]
FdInvalid,
#[error("I/O error on procdog file handle ({0})")]
IoError(nix::Error),
}
pub struct ProcdogAgent {
writer: Option<PipeWriter>,
}
pub fn init(allow_unsupervised: bool) -> Result<ProcdogAgent, Error> {
if let Ok(s_fd) = env::var("PROCDOG_FD") {
let fd = RawFd::from_str_radix(&s_fd, 10).map_err(|_| Error::FdInvalid)?;
let writer = unsafe { PipeWriter::from_raw_fd(fd) };
nix::fcntl::fcntl(
&writer,
nix::fcntl::FcntlArg::F_SETFL(nix::fcntl::OFlag::O_NONBLOCK),
)
.map_err(|errno| Error::IoError(errno))?;
Ok(ProcdogAgent {
writer: Some(writer),
})
} else if allow_unsupervised {
Ok(ProcdogAgent { writer: None })
} else {
Err(Error::Unsupervised)
}
}
impl ProcdogAgent {
pub fn heartbeat(&mut self) {
if let Some(writer) = self.writer.as_mut() {
let buf = [b'H'];
writer
.write(&buf)
.expect("Error writing to procdog supervisor");
}
}
}