]> go.fuhry.dev Git - fsnotify.git/commit
kqueue: don't immediately remove watches for all files in a directory on Delete event...
authorMartin Tournoij <martin@arp242.net>
Sat, 15 Oct 2022 08:33:09 +0000 (10:33 +0200)
committerGitHub <noreply@github.com>
Sat, 15 Oct 2022 08:33:09 +0000 (10:33 +0200)
commit8f6708dd78b4bc6dbea1caec38f710addc3a8fdf
tree14bfc947ba6656b0445129a41629bcc7f8131bf1
parentc62f582adbacae226a7b3794129a12bef7b1c8f1
kqueue: don't immediately remove watches for all files in a directory on Delete event (#526)

The problem was that that on Delete events for directories it would call
Watcher.Remove() for all files in that directory too. This is fine if you call
w.Remove() from the application, but if you rm -rf a directory the directory
itself tends to be the first remove event (on FreeBSD at least):

DELETE WRITE  /tmp/xxx
DELETE        /tmp/xxx/a
DELETE        /tmp/xxx/b
DELETE        /tmp/xxx/c
DELETE        /tmp/xxx/d
DELETE        /tmp/xxx/e
DELETE        /tmp/xxx/f
DELETE        /tmp/xxx/g

So what would happen is that the internal state for /tmp/xxx/a etc. would get
removed, and when the event gets processed we no longer have access to it.

Move Remove() to remove() with a flag to control removing files. If a watched
directory is removed then the files will emit their own delete event, so we
don't really need to do this.

Fixes #514

Also:

- Don't send Remove|Write events; that's never really useful: if it's
  gone, then it's gone. No other backends do this.

- Save a stat call by checking the readdir error instead.

- Don't stat every directory; this isn't really needed, and getting a
  write event before a delete is fine (and this didn't suppress the
  write even anyway).

- Add test/kqueue.c; just a simple implementation to test things.
backend_kqueue.go
fsnotify_test.go
test/kqueue.c [new file with mode: 0644]