diff options
Diffstat (limited to 'third_party/rust/redox_syscall/src/daemon.rs')
-rw-r--r-- | third_party/rust/redox_syscall/src/daemon.rs | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/third_party/rust/redox_syscall/src/daemon.rs b/third_party/rust/redox_syscall/src/daemon.rs new file mode 100644 index 0000000000..6433bcd7d2 --- /dev/null +++ b/third_party/rust/redox_syscall/src/daemon.rs @@ -0,0 +1,62 @@ +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<F: FnOnce(Daemon) -> Infallible>(f: F) -> Result<Infallible> { + 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)) + } + } +} |