Deleting the watched repository in Linux creates an event but does not in Windows
System details
Linux (WSL2):
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.4 LTS
Release: 20.04
Codename: focal
$ uname -r
5.10.102.1-microsoft-standard-WSL2
Windows 11:
21H2 (OS Build 22000.675)- Not running in a container
- Not running as a privileged user
- Not running in a VM
Rust (on both systems):
rustc 1.60.0 (7737e0b5c 2022-04-04)
Notify (on both systems):
notify = "5.0.0-pre.15"
- 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: https://github.com/microsoft/onefuzz/issues/1850
What you did (as detailed as you can)
- Create some directory
b(Linux:mkdir b, Windows:New-Item b -ItemType "directory") - Watch the directory
b(I posted the code below as a minimal repro) - Delete directory
b(Linux:rmdir b, Windows:Remove-Item b) - See on Linux that an event was created
Ok(Event { kind: Remove(File), paths: ["b"], attr:tracker: None, attr:flag: None, attr:info: None, attr:source: None })but on Windows, no event is created
use notify::{Watcher, RecursiveMode};
use std::sync::mpsc::channel;
use std::path::Path;
fn main() {
let (tx, rx) = channel();
let mut watcher = notify::recommended_watcher(tx).unwrap();
let path = Path::new("b");
watcher.watch(&path, RecursiveMode::NonRecursive);
loop {
match rx.recv() {
Ok(e) => println!("{:?}", e),
Err(e) => println!("Error: {:?}", e),
}
}
}
What you expected
The behavior should be consistent across both Linux and Windows. Either both should receive the directory delete event or neither.
What happened
Only the Linux implementation receives the folder delete event.
My guess is that the windows file API simply does not emit events for that case, while on linux it does. Would be interesting to test for this on the other Systems. I did a short search through the docs but I couldn't find anything obvious.
Ok I found something and it's not fun: https://stackoverflow.com/a/49902015/3332686
To summarize: The handle stays open, the folder itself isn't deleted (only when the last handle is closed -> we stop watching it). One could
- call GetFinalPathNameByHandle in addition in a loop and compare if something changed here from the original result
- watch the parent
- watch from a single temporary folder with a symlink.
I'd propose we simply document this behavior and one should watch the parent directory.
Edit to clarify: We simply won't get top-level deletion events on windows.
Thanks for looking into this! I definitely think that documenting the behavior and the parent directory workaround is a good idea.
It seems there are some solutions like the ones listed in that stackoverflow answer. In notify's case it could be some separate thread that occasionally polls the watched directory using GetFinalPathNameByHandle but I understand that's far from a 'clean' implementation.
fyi: behaviour is documented and links to this issue for now