Subject: bug#51146: 29.0.50; file-notify-add-watch not reporting changes of files

From: Michael Albinus <[email-masked]>
Date: Fri, 15 Oct 2021 14:06:51 +0200

Carlos Pita <[email-masked]> writes:

> Hi all,

Hi Carlos,

> the docstring for file-notify-add-watch states:
>    
>     If FILE is a directory, ‘change’ watches for file creation or
>     deletion in that directory.  This does not work recursively.
>
> OTOH the elisp documentation in [1] states:
>
>      If file is a directory, changes for all files in that directory
>      will be notified. This does not work recursively.
>
> So the statements seem contradictory regarding the notification of
> changes in the contents of the files (not their creation or
> deletion). In the most lenient interpretation, the docstring may be
> considered silent in this regard.

Well, the situation is complex. We have 6 (in words: "six") different
file notification libraries: inotify, kqueue, gfilenotify, w32notify,
inotifywatch, and gio. The two latter libraries are for remote file
systems.

gfilenotify / gio know different implementations, called monitors. Until
now I could test 5 (in words: "five") of them: GFamFileMonitor,
GFamDirectoryMonitor, GInotifyFileMonitor, GKqueueFileMonitor, and
GPollFileMonitor. Likely there are more.

All of them behave slightly different. filenotify.el is the attempt to
harmonize them, especially to let them fire the same events. This has
restrictions.

If you want to get an impressions, I recommend you to read
test/lisp/filenotify-tests.el.

> This little experiment shows that, at least in my setup, a change in the
> content of a file is not notified:
>
>     (defun my-watcher (event) (message "Not in my watch: %s" event))
>
>     (file-notify-add-watch "/tmp/some-dir" '(change) #'my-watcher)
>
> Then:
>
>     touch /tmp/some-dir/x => Not in my watch: (18 created /tmp/some-dir/x)
>     echo dsds > /tmp/some-dir/x => Nothing
>     rm  /tmp/some-dir/x => Not in my watch: (18 deleted /tmp/some-dir/x)

Running your test with some of them shows:

inotify
=======
touch /tmp/x => Not in my watch: ((1 . 0) created /tmp/x)
echo dsds > /tmp/x => Not in my watch: ((1 . 0) changed /tmp/x)
rm  /tmp/x => Not in my watch: ((1 . 0) deleted /tmp/x)

kqueue
======
touch /tmp/x => Not in my watch: (9 created /tmp/x)
echo dsds > /tmp/x => Nothing
rm  /tmp/x => Not in my watch: (9 deleted /tmp/x)

gfilenotify (GFamFileMonitor)
===========
touch /tmp/x => Not in my watch: (8590168344 created /tmp/x)
echo dsds > /tmp/x => Not in my watch: (8590168344 changed /tmp/x)
rm  /tmp/x => Not in my watch: (8590168344 deleted /tmp/x)

w32notify
=========
touch c:/Users/albinus/AppData/Roaming/x => Not in my watch: (649583674484 created c:/Users/albinus/AppData/Roaming/x)
echo dsds > c:/Users/albinus/AppData/Roaming/x => Not in my watch: (649583674484 changed c:/Users/albinus/AppData/Roaming/x)
rm  c:/Users/albinus/AppData/Roaming/x => Not in my watch: (649583674484 deleted c:/Users/albinus/AppData/Roaming/x)

inotifywait
===========
touch /tmp/x => Not in my watch: (inotifywait created /ssh:gandalf:/tmp/x)
echo dsds > /tmp/x => Not in my watch: (inotifywait changed /ssh:gandalf:/tmp/x)
rm  /tmp/x => Not in my watch: (inotifywait deleted /ssh:gandalf:/tmp/x)

gio (GKqueueFileMonitor)
===
touch /tmp/x => Not in my watch: (gio created /ssh:freebsd12:/tmp/x)
echo dsds > /tmp/x => Nothing
rm  /tmp/x => Not in my watch: (gio deleted /ssh:freebsd12:/tmp/x)

gio (GPollFileMonitor)
===
touch /tmp/x => Not in my watch: (gio created /mock:win10:/tmp/x)
echo dsds > /tmp/x => Not in my watch: (gio changed /mock:win10:/tmp/x)
rm  /tmp/x => Not in my watch: (gio deleted /mock:win10:/tmp/x)

> So according to the elisp manual this is a bug, but according to the
> docstring it seemingly isn't. I'm with the manual in this one.

In case a directory is watched, creation and deletion of a file are
notified. Changes to a file are notified depending on the underlying
library, in short everything which depends on kqueue does not notify
such a change.

I will adapt the docstring of file-notify-add-watch as well as the elisp
manual accordingly.

> Best regards,
> Carlos

Best regards, Michael.