commit | 4da3e2cfbabc9f751898f250b49f2439785783a1 | [log] [tgz] |
---|---|---|
author | Aaron L <aaron@bettercoder.net> | Wed Mar 29 04:21:07 2017 |
committer | Mark Bates <mark@markbates.com> | Wed Mar 29 11:06:42 2017 |
tree | 95b6c61860de89ebfaa370b07c1067405bbeefc1 | |
parent | ff7bc41d4007f67e5456703c34342df4e0113f64 [diff] |
Fix deadlock in Remove (linux/inotify) Several people have reported this issue where if you are using a single goroutine to watch for fs events and you call Remove in that goroutine it can deadlock. The cause for this is that the Remove was made synchronous by PR #73. The reason for this was to try and ensure that maps were no longer leaking. In this PR: IN_IGNORE was used as the event to ensure map cleanup. This worked fine when Remove() was called and the next event was IN_IGNORE, but when a different event was received the main goroutine that's supposed to be reading from the Events channel would be stuck waiting for the sync.Cond, which would never be hit because the select would then block waiting for someone to receive the non-IN_IGNORE event from the channel so it could proceed to process the IN_IGNORE event that was waiting in the queue. Deadlock :) Removing the synchronization then created two nasty races where Remove followed by Remove would error unnecessarily, and one where Remove followed by an Add could result in the maps being cleaned up AFTER the Add call which means the inotify watch is active, but our maps don't have the values anymore. It then becomes impossible to delete the watches via the fsnotify code since it checks it's local data before calling InotifyRemove. This code attempts to use IN_DELETE_SELF as a means to know when a watch was deleted as part of an unlink(). That means that we didn't delete the watch via the fsnotify lib and we should clean up our maps since that watch no longer exists. This allows us to clean up the maps immediately when calling Remove since we no longer try to synchronize cleanup using IN_IGNORE as the sync point. - Fix #195 - Fix #123 - Fix #115
fsnotify utilizes golang.org/x/sys rather than syscall
from the standard library. Ensure you have the latest version installed by running:
go get -u golang.org/x/sys/...
Cross platform: Windows, Linux, BSD and macOS.
Adapter | OS | Status |
---|---|---|
inotify | Linux 2.6.27 or later, Android* | Supported |
kqueue | BSD, macOS, iOS* | Supported |
ReadDirectoryChangesW | Windows | Supported |
FSEvents | macOS | Planned |
FEN | Solaris 11 | In Progress |
fanotify | Linux 2.6.37+ | |
USN Journals | Windows | Maybe |
Polling | All | Maybe |
* Android and iOS are untested.
Please see the documentation and consult the FAQ for usage information.
fsnotify is a fork of howeyc/fsnotify with a new API as of v1.0. The API is based on this design document.
All releases are tagged based on Semantic Versioning. Further API changes are planned, and will be tagged with a new major revision number.
Go 1.6 supports dependencies located in the vendor/
folder. Unless you are creating a library, it is recommended that you copy fsnotify into vendor/github.com/fsnotify/fsnotify
within your project, and likewise for golang.org/x/sys
.
Please refer to CONTRIBUTING before opening an issue or pull request.
See example_test.go.
When a file is moved to another directory is it still being watched?
No (it shouldn't be, unless you are watching where it was moved to).
When I watch a directory, are all subdirectories watched as well?
No, you must add watches for any directory you want to watch (a recursive watcher is on the roadmap #18).
Do I have to watch the Error and Event channels in a separate goroutine?
As of now, yes. Looking into making this single-thread friendly (see howeyc #7)
Why am I receiving multiple events for the same file on OS X?
Spotlight indexing on OS X can result in multiple events (see howeyc #62). A temporary workaround is to add your folder(s) to the Spotlight Privacy settings until we have a native FSEvents implementation (see #11).
How many files can be watched at once?
There are OS-specific limits as to how many watches can be created: