summaryrefslogtreecommitdiffstats
path: root/third_party/rust/redox_syscall/src/daemon.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/redox_syscall/src/daemon.rs')
-rw-r--r--third_party/rust/redox_syscall/src/daemon.rs62
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))
+ }
+ }
+}