use core::convert::Infallible; use super::{ clone, CloneFlags, close, EIO, Error, exit, pipe2, read, Result, write, }; #[must_use = "Daemon::ready must be called"] pub struct Daemon { write_pipe: usize, } impl Daemon { pub fn new Infallible>(f: F) -> Result { let mut pipes = [0; 2]; pipe2(&mut pipes, 0)?; let [read_pipe, write_pipe] = pipes; if unsafe { clone(CloneFlags::empty())? } == 0 { let _ = close(read_pipe); f(Daemon { write_pipe, }); // TODO: Replace Infallible with the never type once it is stabilized. unreachable!(); } else { let _ = close(write_pipe); let mut data = [0]; let res = read(read_pipe, &mut data); let _ = close(read_pipe); if res? == 1 { exit(data[0] as usize)?; unreachable!(); } else { Err(Error::new(EIO)) } } } pub fn ready(self) -> Result<()> { let res = write(self.write_pipe, &[0]); let _ = close(self.write_pipe); if res? == 1 { Ok(()) } else { Err(Error::new(EIO)) } } }