notify icon indicating copy to clipboard operation
notify copied to clipboard

Deleting the watched repository in Linux creates an event but does not in Windows

Open tevoinea opened this issue 3 years ago • 4 comments

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)

  1. Create some directory b (Linux: mkdir b, Windows: New-Item b -ItemType "directory")
  2. Watch the directory b (I posted the code below as a minimal repro)
  3. Delete directory b (Linux: rmdir b, Windows: Remove-Item b)
  4. 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.

tevoinea avatar May 12 '22 18:05 tevoinea

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.

0xpr03 avatar May 12 '22 20:05 0xpr03

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.

0xpr03 avatar May 12 '22 21:05 0xpr03

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.

tevoinea avatar May 13 '22 13:05 tevoinea

fyi: behaviour is documented and links to this issue for now

0xpr03 avatar Aug 30 '22 17:08 0xpr03