You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
OS/Platform name and version: FreeBSD freebsd 14.1-RELEASE FreeBSD 14.1-RELEASE releng/14.1-n267679-10e31f0946d8 GENERIC amd64 (running under QEMU)
Rust version (if building from source): rustc --version: rustc 1.81.0 (eeb90cda1 2024-09-04)
Notify version (or commit hash if building from git): 6.1.1
Note: the issue doesn't seem to be FreeBSD-specific (as far as I can tell, it happens on all platforms that use kqueue).
If you're coming from a project that makes use of Notify, what it is, and a link to the downstream issue if there is one: in Arti, we're using notify to watch configuration files for changes. The bug described here is causing one of our tests to stall: https://gitlab.torproject.org/tpo/core/arti/-/issues/1644
What you did (as detailed as you can)
I set up a non-recursive watcher for a directory that contains a single file foo. I created another file bar in the directory, expecting to receive an Event associated with the path of bar, but instead got an event for foo.
use notify::{Config,RecommendedWatcher,RecursiveMode,Watcher};use std::path::PathBuf;use std::sync::mpsc;use temp_dir::TempDir;fnwrite_file(dir:&TempDir,name:&str,data:&[u8]) -> PathBuf{let path = dir.path().join(name);
std::fs::write(&path, data).unwrap();
path
}fnmain(){let temp_dir = TempDir::new().unwrap();// Prepopulate temp_dir with a file.let _:PathBuf = write_file(&temp_dir,"foo",b"hello");let(tx, rx) = mpsc::channel();letmut watcher =
RecommendedWatcher::new(move |event| tx.send(event).unwrap(),Config::default()).unwrap();println!("watching {}", temp_dir.path().display());
watcher
.watch(temp_dir.path(),RecursiveMode::NonRecursive).unwrap();// We haven't triggered any events since starting the watcherassert!(rx.try_recv().is_err());// Write a file to the watched directory.// This should trigger an event where one of the paths is// "<temp_dir>/bar".let expected_path = write_file(&temp_dir,"bar",b"good-bye");let ev = rx.recv().unwrap().unwrap();println!("{:#?}", ev);assert!(
ev.paths.contains(&expected_path),"expected event for {}, but got event for {:?}?!",
expected_path.display(),
ev.paths,);// Note: as expected, writing the second file triggers a single event:// * with the inotify backend, the event is associated with the newly created file "bar",// as expected// * with the kqueue backend, the event is wrongly associated with file "foo"}
watching /tmp/tb59-0
Event {
kind: Create(
File,
),
paths: [
"/tmp/tb59-0/foo",
],
attr:tracker: None,
attr:flag: None,
attr:info: None,
attr:source: None,
}
thread main panicked at src/main.rs:38:5:
expected event for /tmp/tb59-0/bar, but got event for ["/tmp/tb59-0/foo"]?!
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
I think the bug is in handle_kqueue's handling of kqueue::Vnode::Write:
it assumes that all the files from the watched directory are already in self.watches (which isn't the case for non-recursive watchers)
it then looks for the first entry from std::fs::read_dir(&path) that is not in self.watches. However, if the watcher is non-recursive, this entry won't necessarily be the one that triggered the kqueue::Vnode::Write event
I can try to come up with a patch to fix this, if you'd like.
The text was updated successfully, but these errors were encountered:
zydou
pushed a commit
to zydou/arti
that referenced
this issue
Oct 17, 2024
… have inotify.
On windows and platforms that support inotify (i.e. linux and android),
we continue using the recommended watcher. On platforms that use kqueue,
we switch to a polling watcher to work around a [notify bug] that
manifests when using a non-recursive watcher to watch a directory.
This commit is best reviewed with `git diff --ignore-all-space`.
Closes #1644
[notify bug]: notify-rs/notify#644
System details
FreeBSD freebsd 14.1-RELEASE FreeBSD 14.1-RELEASE releng/14.1-n267679-10e31f0946d8 GENERIC amd64
(running under QEMU)rustc --version
:rustc 1.81.0 (eeb90cda1 2024-09-04)
Note: the issue doesn't seem to be FreeBSD-specific (as far as I can tell, it happens on all platforms that use kqueue).
notify
to watch configuration files for changes. The bug described here is causing one of our tests to stall: https://gitlab.torproject.org/tpo/core/arti/-/issues/1644What you did (as detailed as you can)
I set up a non-recursive watcher for a directory that contains a single file
foo
. I created another filebar
in the directory, expecting to receive anEvent
associated with the path ofbar
, but instead got an event forfoo
.with
Cargo.toml
:The assertion fails on platforms using the
kqueue
backend. With theinotify
backend, it works as expected.What you expected
What happened
The assertion failed
I think the bug is in
handle_kqueue
's handling ofkqueue::Vnode::Write
:self.watches
(which isn't the case for non-recursive watchers)std::fs::read_dir(&path)
that is not inself.watches
. However, if the watcher is non-recursive, this entry won't necessarily be the one that triggered thekqueue::Vnode::Write
eventI can try to come up with a patch to fix this, if you'd like.
The text was updated successfully, but these errors were encountered: