Repository: hannobraun/inotify-rs (language: rust)

Issue:
 Inotify::read_events does not read all events
The documentation for `Inotify::read_events` says:

> Returns any available events
>
> Returns an iterator over all events that are currently available.

However, the function only reads one buffers' worth of data from the inotify file descriptor; if there are more events available than can fit in the buffer, the returned `Events` iterator returns `None` without trying to read any more from the file descriptor.

This causes the `notify` crate to delay reporting events. That crate registers its inotify file descriptor with `mio::PollOpt::edge()`, which requests edge-triggered notifications, as described here: https://docs.rs/mio/0.6.15/mio/struct.Poll.html#edge-triggered-and-level-triggered

> If when the socket was registered with `Poll`, edge triggered events were requested, then the call to `Poll::poll` done in step 5 will (probably) hang despite there being another 1kb still present in the socket read buffer. The reason for this is that edge-triggered mode delivers events only when changes occur on the monitored `Evented`. So, in step 5 the caller might end up waiting for some data that is already present inside the socket buffer.

This means that `notify::inotify::EventLoop::handle_inotify` is indeed counting on `inotify::Inotify::read_events` to behave as documented: to fully consume all available data from the file descriptor. Indeed, if I change `notify::inotify::EventLoop::new` to request level-triggered events on `inotify_fd`, I get all my file creation notifications.


Discussion / hints:

Fix patch:
diff --git a/src/inotify.rs b/src/inotify.rs
index 1b748f5..f0981fd 100644
--- a/src/inotify.rs
+++ b/src/inotify.rs
@@ -295,12 +295,12 @@ impl Inotify {
         result
     }
 
-    /// Returns any available events
+    /// Returns one buffer's worth of available events
     ///
-    /// Returns an iterator over all events that are currently available. If no
-    /// events are available, an iterator is still returned. If you need a
-    /// method that will block until at least one event is available, please
-    /// consider [`read_events_blocking`].
+    /// Reads as many events as possible into `buffer`, and returns an iterator
+    /// over them. If no events are available, an iterator is still returned. If
+    /// you need a method that will block until at least one event is available,
+    /// please consider [`read_events_blocking`].
     ///
     /// Please note that inotify will merge identical unread events into a
     /// single event. This means this method can not be used to count the number


Test patch: