From ef919f3d5216a12b6c80637ffd617db935dc4c96 Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jeremy@system76.com>
Date: Sat, 22 Dec 2018 08:02:00 -0700
Subject: [PATCH] Implement EINTR for anything using wait_queue

---
 src/event.rs           |  4 ++--
 src/scheme/debug.rs    |  4 +++-
 src/scheme/user.rs     |  5 ++++-
 src/sync/wait_map.rs   |  1 +
 src/sync/wait_queue.rs | 14 ++++++++------
 5 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/src/event.rs b/src/event.rs
index f7cef70a..dbe908f4 100644
--- a/src/event.rs
+++ b/src/event.rs
@@ -7,7 +7,7 @@ use context;
 use scheme::{self, SchemeId};
 use sync::WaitQueue;
 use syscall::data::Event;
-use syscall::error::{Error, Result, EBADF, ESRCH};
+use syscall::error::{Error, Result, EBADF, EINTR, ESRCH};
 
 int_like!(EventQueueId, AtomicEventQueueId, usize, AtomicUsize);
 
@@ -25,7 +25,7 @@ impl EventQueue {
     }
 
     pub fn read(&self, events: &mut [Event]) -> Result<usize> {
-        Ok(self.queue.receive_into(events, true))
+        self.queue.receive_into(events, true).ok_or(Error::new(EINTR))
     }
 
     pub fn write(&self, events: &[Event]) -> Result<usize> {
diff --git a/src/scheme/debug.rs b/src/scheme/debug.rs
index 17e016fa..4f1cec5b 100644
--- a/src/scheme/debug.rs
+++ b/src/scheme/debug.rs
@@ -68,7 +68,9 @@ impl Scheme for DebugScheme {
             *handles.get(&id).ok_or(Error::new(EBADF))?
         };
 
-        Ok(INPUT.call_once(init_input).receive_into(buf, flags & O_NONBLOCK != O_NONBLOCK))
+        INPUT.call_once(init_input)
+            .receive_into(buf, flags & O_NONBLOCK != O_NONBLOCK)
+            .ok_or(Error::new(EINTR))
     }
 
     /// Write the `buffer` to the `file`
diff --git a/src/scheme/user.rs b/src/scheme/user.rs
index f894d8ea..eab5704c 100644
--- a/src/scheme/user.rs
+++ b/src/scheme/user.rs
@@ -168,7 +168,10 @@ impl UserInner {
 
     pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
         let packet_buf = unsafe { slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut Packet, buf.len()/mem::size_of::<Packet>()) };
-        Ok(self.todo.receive_into(packet_buf, self.flags & O_NONBLOCK != O_NONBLOCK) * mem::size_of::<Packet>())
+        self.todo
+            .receive_into(packet_buf, self.flags & O_NONBLOCK != O_NONBLOCK)
+            .map(|count| count * mem::size_of::<Packet>())
+            .ok_or(Error::new(EINTR))
     }
 
     pub fn write(&self, buf: &[u8]) -> Result<usize> {
diff --git a/src/sync/wait_map.rs b/src/sync/wait_map.rs
index 45c692af..aedcef50 100644
--- a/src/sync/wait_map.rs
+++ b/src/sync/wait_map.rs
@@ -27,6 +27,7 @@ impl<K, V> WaitMap<K, V> where K: Clone + Ord {
             if let Some(value) = self.receive_nonblock(key) {
                 return value;
             }
+            //TODO: use false from wait condition to indicate EINTR
             let _ = self.condition.wait();
         }
     }
diff --git a/src/sync/wait_queue.rs b/src/sync/wait_queue.rs
index 384a125b..766ce895 100644
--- a/src/sync/wait_queue.rs
+++ b/src/sync/wait_queue.rs
@@ -28,20 +28,22 @@ impl<T> WaitQueue<T> {
         self.inner.lock().is_empty()
     }
 
-    pub fn receive(&self) -> T {
+    pub fn receive(&self) -> Option<T> {
         loop {
             if let Some(value) = self.inner.lock().pop_front() {
-                return value;
+                return Some(value);
+            }
+            if ! self.condition.wait() {
+                return None;
             }
-            let _ = self.condition.wait();
         }
     }
 
-    pub fn receive_into(&self, buf: &mut [T], block: bool) -> usize {
+    pub fn receive_into(&self, buf: &mut [T], block: bool) -> Option<usize> {
         let mut i = 0;
 
         if i < buf.len() && block {
-            buf[i] = self.receive();
+            buf[i] = self.receive()?;
             i += 1;
         }
 
@@ -57,7 +59,7 @@ impl<T> WaitQueue<T> {
             }
         }
 
-        i
+        Some(i)
     }
 
     pub fn send(&self, value: T) -> usize {
-- 
GitLab