hannobraun / inotify-rs

Idiomatic inotify wrapper for the Rust programming language
ISC License
254 stars 64 forks source link

Example in API reference is broken #215

Open Chaqua opened 5 months ago

Chaqua commented 5 months ago

I just followed the example, the only thing I changed was the read_events_blocking to read_events, and now, when executing the program, it throws the following error: 'Error reading events: Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }

Even if changing it back to read_events_blocking it still doesn't work, and the error percists.

Code:

async fn inot() {
    if let Some(mut home_dir) = dirs::home_dir() {
        let folder_name = "Google Drive";
        home_dir.push(folder_name);
        let mut inotify = Inotify::init().expect("Error initalizing inotify");

        inotify
            .watches()
            .add(home_dir, WatchMask::MODIFY | WatchMask::DELETE)
            .expect("Failed to watch file");

        let mut buffer = [0; 1024];
        let events = inotify
            .read_events(&mut buffer)
            .expect("Error reading events");

        for event in events {
            println!("{event:?}");
        }
    }
}
Chaqua commented 5 months ago

Using the example code from the github works perfectly fine. The code from the Docs doesn't, as written down above:

Docs

Example

use inotify::{
    Inotify,
    WatchMask,
};

let mut inotify = Inotify::init()
    .expect("Error while initializing inotify instance");

// Watch for modify and close events.
inotify
    .watches()
    .add(
        "/tmp/inotify-rs-test-file",
        WatchMask::MODIFY | WatchMask::CLOSE,
    )
    .expect("Failed to add file watch");

// Read events that were added with `Watches::add` above.
let mut buffer = [0; 1024];
let events = inotify.read_events_blocking(&mut buffer)
    .expect("Error while reading events");

for event in events {
    // Handle event
}
hannobraun commented 5 months ago

Thank you for opening this issue, @Chaqua! I'm trying to understand, if there's a problem that needs to be addressed within this repository.


You said above:

I just followed the example, the only thing I changed was the read_events_blocking to read_events

And then:

The code from the Docs doesn't, as written down above:

It's not clear to me, whether the unchanged example from the documentation ever worked for you. Can you confirm whether this is the case or not?


when executing the program, it throws the following error: 'Error reading events: Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }

Even if changing it back to read_events_blocking it still doesn't work, and the error percists.

It's very weird and surprising, that it persists after a restart. Are you sure that you were running the version of the code you expected to run? Can you reproduce this reliably?

Chaqua commented 5 months ago

Sorry for not expressing it clearly. What I meant is, that on the Docs.rs webpage (docs), there is the following code:

use inotify::{
    Inotify,
    WatchMask,
};

let mut inotify = Inotify::init()
    .expect("Error while initializing inotify instance");

// Watch for modify and close events.
inotify
    .watches()
    .add(
        "/tmp/inotify-rs-test-file",
        WatchMask::MODIFY | WatchMask::CLOSE,
    )
    .expect("Failed to add file watch");

// Read events that were added with `Watches::add` above.
let mut buffer = [0; 1024];
let events = inotify.read_events_blocking(&mut buffer)
    .expect("Error while reading events");

for event in events {
    // Handle event
}

Which doesn't work for me. Even after rebooting, it doesn't. The code you provide on the github here works perfectly fine tho.

I am running Linux: 6.8.1-arch1-1

hannobraun commented 5 months ago

Thank you for reporting back. Let's reopen this issue then, to track that the example needs to be fixed or removed.

If somebody wants to look into it, that would be welcome. But I'd also be happy to merge a pull request that just removes it, maybe referencing the example in the repository.

trinitronx commented 1 month ago

I encountered a similar error when investigating a codebase that uses this library: findex.

It similarly uses a pattern like the one in the documentation, except uses read_events(), the non-blocking function variant. As it turns out, this does throw an Error: Resource temporarily unavailable with std::io::ErrorKind of WouldBlock. In that project, it just logs the errors as warnings, but it can get obnoxious when this happens very frequently and fills up log files on disk.

From the Rust docs for std::io::ErrorKind:

/// The operation needs to block to complete, but the blocking operation was
/// requested to not occur.
#[stable(feature = "rust1", since = "1.0.0")]
WouldBlock,

So, when using the read_events() function for non-blocking behavior watching a directory, some operation is being performed that would result in blocking. So, the error exception is thrown (from read_into_buffer()) and caught by the match statement in the code calling read_events().

It looks like these errors can be silenced by doing something like in the example in the inotify::Inotify documentation for read_events():

let mut buffer = [0; 1024];
let events = loop {
    match inotify.read_events(&mut buffer) {
        Ok(events) => break events,
        Err(error) if error.kind() == ErrorKind::WouldBlock => continue, // <- Here they are ignored 
        _ => panic!("Error while reading events"),
    }
};
hannobraun commented 1 month ago

Thank you for looking into this, @trinitronx!

trinitronx commented 3 weeks ago

Should now be fixed in downstream findex code by mdgaziur/findex#52! :tada: :rocket:

Feel free to reference that code in examples 😄