Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/exp/inotify: Remove watches from the internal map even if a directory is deleted #16709

Closed
agorman opened this issue Aug 15, 2016 · 5 comments

Comments

@agorman
Copy link

agorman commented Aug 15, 2016

What version of Go are you using (go version)?

go version go1.6.1 linux/amd64

What operating system and processor architecture are you using?

CentOS 6
Intel Core 2 Duo
2.6.32-431.20.3.el6.centos.plus.x86_64 #1 SMP Thu Jun 19 23:04:15 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

What did you do?

I deleted a directory that was being watched.

What did you expect to see?

If a directory is deleted I expect to be able to watch another directory that gets created with the same name.

What did you see instead?

If a watched directory is deleted from the OS it will never be removed from the watches map which cases a directory with the same name to never be able to be watched again during the programs execution.

My proposed change: agorman/exp@66dcf71

I created a gist for a program that shows the bug. You can test it against the current code and my proposed change. https://gist.github.com/agorman/000e5aca46827057accc8312bf55d989

Thanks

@rakyll rakyll changed the title inotify: Remove watches from the internal map even if a directory is deleted x/exp/inotify: Remove watches from the internal map even if a directory is deleted Aug 16, 2016
@rakyll rakyll added this to the Unreleased milestone Aug 16, 2016
@chenchun
Copy link

Also happened to find this problem. I deleted a directory that was being watched, then I tried to invoke inotify.RemoveWatch and it erred out "inotify_rm_watch: invalid argument". I think disallowing to remove watch on a deleted directory is the normal behavior of kernel. inotify.go should delete the keys from watches and paths map and suppress the error returned by syscall.InotifyRmWatch in this situation.

@agorman I think you fix is wrong, ok in the statement if !ok && success == -1 {should always be true. My fix is as follows

diff --git a/vendor/golang.org/x/exp/inotify/inotify_linux.go b/vendor/golang.org/x/exp/inotify/inotify_linux.go
index 901f308..c8bd944 100644
--- a/vendor/golang.org/x/exp/inotify/inotify_linux.go
+++ b/vendor/golang.org/x/exp/inotify/inotify_linux.go
@@ -141,7 +141,10 @@ func (w *Watcher) RemoveWatch(path string) error {
        }
        success, errno := syscall.InotifyRmWatch(w.fd, watch.wd)
        if success == -1 {
-               return os.NewSyscallError("inotify_rm_watch", errno)
+               // If path not exists, we should continue delete keys from watchs and paths
+               if _, err := os.Stat(path); err == nil {
+                       return os.NewSyscallError("inotify_rm_watch", errno)
+               }
        }
        delete(w.watches, path)
        // Locking here to protect the read from paths in readEvents.

@agorman
Copy link
Author

agorman commented Aug 16, 2016

Doh, you're right about my logic error. Good catch. I don't think this change quite fixes it either though. If a directory was deleted and then RemoveWatch is called it will still error without deleting the watch internally.

I propose that we just move the internal deletes up and keep the error handling the same. That way users can handle the error as they see fit but the watch is cleaned up properly internally.

agorman/exp@9382284

@chenchun
Copy link

My patch fix the situation that the path was deleted and retrying to remove the watch is useless. But if InotifyRmWatch returns error due to other problems which we don't know if retry helps, I think maybe we need to add a forceRemove bool field to func (w *Watcher) RemoveWatch(path string) error. If forceRemove is set, we delete keys from watches and paths map even if error returns.

@agorman
Copy link
Author

agorman commented Aug 16, 2016

I'm fine with not doing the syscall to inotify if the directory doesn't exist as long as the internal maps are cleaned up even if an error is returned. I don't think a user should have to force anything to allow for the watches to be removed internally even if there is no actual inotify watch.

@rsc
Copy link
Contributor

rsc commented Oct 6, 2016

Deleted this code instead. See github.com/fsnotify for more maintained code.

@rsc rsc closed this as completed Oct 6, 2016
@golang golang locked and limited conversation to collaborators Oct 6, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants