mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Update fsnotify to fix deadlock in removing watch
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
parent
a4bdb304e2
commit
e8aa22645b
4 changed files with 77 additions and 32 deletions
|
@ -85,7 +85,7 @@ github.com/philhofer/fwd 98c11a7a6ec829d672b03833c3d69a7fae1ca972
|
||||||
github.com/tinylib/msgp 75ee40d2601edf122ef667e2a07d600d4c44490c
|
github.com/tinylib/msgp 75ee40d2601edf122ef667e2a07d600d4c44490c
|
||||||
|
|
||||||
# fsnotify
|
# fsnotify
|
||||||
github.com/fsnotify/fsnotify v1.4.2
|
github.com/fsnotify/fsnotify 4da3e2cfbabc9f751898f250b49f2439785783a1
|
||||||
|
|
||||||
# awslogs deps
|
# awslogs deps
|
||||||
github.com/aws/aws-sdk-go v1.4.22
|
github.com/aws/aws-sdk-go v1.4.22
|
||||||
|
|
37
vendor/github.com/fsnotify/fsnotify/README.md
generated
vendored
37
vendor/github.com/fsnotify/fsnotify/README.md
generated
vendored
|
@ -8,14 +8,14 @@ fsnotify utilizes [golang.org/x/sys](https://godoc.org/golang.org/x/sys) rather
|
||||||
go get -u golang.org/x/sys/...
|
go get -u golang.org/x/sys/...
|
||||||
```
|
```
|
||||||
|
|
||||||
Cross platform: Windows, Linux, BSD and OS X.
|
Cross platform: Windows, Linux, BSD and macOS.
|
||||||
|
|
||||||
|Adapter |OS |Status |
|
|Adapter |OS |Status |
|
||||||
|----------|----------|----------|
|
|----------|----------|----------|
|
||||||
|inotify |Linux 2.6.27 or later, Android\*|Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify)|
|
|inotify |Linux 2.6.27 or later, Android\*|Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify)|
|
||||||
|kqueue |BSD, OS X, iOS\*|Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify)|
|
|kqueue |BSD, macOS, iOS\*|Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify)|
|
||||||
|ReadDirectoryChangesW|Windows|Supported [![Build status](https://ci.appveyor.com/api/projects/status/ivwjubaih4r0udeh/branch/master?svg=true)](https://ci.appveyor.com/project/NathanYoungman/fsnotify/branch/master)|
|
|ReadDirectoryChangesW|Windows|Supported [![Build status](https://ci.appveyor.com/api/projects/status/ivwjubaih4r0udeh/branch/master?svg=true)](https://ci.appveyor.com/project/NathanYoungman/fsnotify/branch/master)|
|
||||||
|FSEvents |OS X |[Planned](https://github.com/fsnotify/fsnotify/issues/11)|
|
|FSEvents |macOS |[Planned](https://github.com/fsnotify/fsnotify/issues/11)|
|
||||||
|FEN |Solaris 11 |[In Progress](https://github.com/fsnotify/fsnotify/issues/12)|
|
|FEN |Solaris 11 |[In Progress](https://github.com/fsnotify/fsnotify/issues/12)|
|
||||||
|fanotify |Linux 2.6.37+ | |
|
|fanotify |Linux 2.6.37+ | |
|
||||||
|USN Journals |Windows |[Maybe](https://github.com/fsnotify/fsnotify/issues/53)|
|
|USN Journals |Windows |[Maybe](https://github.com/fsnotify/fsnotify/issues/53)|
|
||||||
|
@ -23,7 +23,7 @@ Cross platform: Windows, Linux, BSD and OS X.
|
||||||
|
|
||||||
\* Android and iOS are untested.
|
\* Android and iOS are untested.
|
||||||
|
|
||||||
Please see [the documentation](https://godoc.org/github.com/fsnotify/fsnotify) for usage. Consult the [Wiki](https://github.com/fsnotify/fsnotify/wiki) for the FAQ and further information.
|
Please see [the documentation](https://godoc.org/github.com/fsnotify/fsnotify) and consult the [FAQ](#faq) for usage information.
|
||||||
|
|
||||||
## API stability
|
## API stability
|
||||||
|
|
||||||
|
@ -41,6 +41,35 @@ Please refer to [CONTRIBUTING][] before opening an issue or pull request.
|
||||||
|
|
||||||
See [example_test.go](https://github.com/fsnotify/fsnotify/blob/master/example_test.go).
|
See [example_test.go](https://github.com/fsnotify/fsnotify/blob/master/example_test.go).
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
**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][#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][#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:
|
||||||
|
* Linux: /proc/sys/fs/inotify/max_user_watches contains the limit, reaching this limit results in a "no space left on device" error.
|
||||||
|
* BSD / OSX: sysctl variables "kern.maxfiles" and "kern.maxfilesperproc", reaching these limits results in a "too many open files" error.
|
||||||
|
|
||||||
|
[#62]: https://github.com/howeyc/fsnotify/issues/62
|
||||||
|
[#18]: https://github.com/fsnotify/fsnotify/issues/18
|
||||||
|
[#11]: https://github.com/fsnotify/fsnotify/issues/11
|
||||||
|
[#7]: https://github.com/howeyc/fsnotify/issues/7
|
||||||
|
|
||||||
[contributing]: https://github.com/fsnotify/fsnotify/blob/master/CONTRIBUTING.md
|
[contributing]: https://github.com/fsnotify/fsnotify/blob/master/CONTRIBUTING.md
|
||||||
|
|
||||||
## Related Projects
|
## Related Projects
|
||||||
|
|
4
vendor/github.com/fsnotify/fsnotify/fsnotify.go
generated
vendored
4
vendor/github.com/fsnotify/fsnotify/fsnotify.go
generated
vendored
|
@ -9,6 +9,7 @@ package fsnotify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -60,3 +61,6 @@ func (op Op) String() string {
|
||||||
func (e Event) String() string {
|
func (e Event) String() string {
|
||||||
return fmt.Sprintf("%q: %s", e.Name, e.Op.String())
|
return fmt.Sprintf("%q: %s", e.Name, e.Op.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Common errors that can be reported by a watcher
|
||||||
|
var ErrEventOverflow = errors.New("fsnotify queue overflow")
|
||||||
|
|
66
vendor/github.com/fsnotify/fsnotify/inotify.go
generated
vendored
66
vendor/github.com/fsnotify/fsnotify/inotify.go
generated
vendored
|
@ -24,7 +24,6 @@ type Watcher struct {
|
||||||
Events chan Event
|
Events chan Event
|
||||||
Errors chan error
|
Errors chan error
|
||||||
mu sync.Mutex // Map access
|
mu sync.Mutex // Map access
|
||||||
cv *sync.Cond // sync removing on rm_watch with IN_IGNORE
|
|
||||||
fd int
|
fd int
|
||||||
poller *fdPoller
|
poller *fdPoller
|
||||||
watches map[string]*watch // Map of inotify watches (key: path)
|
watches map[string]*watch // Map of inotify watches (key: path)
|
||||||
|
@ -56,7 +55,6 @@ func NewWatcher() (*Watcher, error) {
|
||||||
done: make(chan struct{}),
|
done: make(chan struct{}),
|
||||||
doneResp: make(chan struct{}),
|
doneResp: make(chan struct{}),
|
||||||
}
|
}
|
||||||
w.cv = sync.NewCond(&w.mu)
|
|
||||||
|
|
||||||
go w.readEvents()
|
go w.readEvents()
|
||||||
return w, nil
|
return w, nil
|
||||||
|
@ -103,21 +101,23 @@ func (w *Watcher) Add(name string) error {
|
||||||
var flags uint32 = agnosticEvents
|
var flags uint32 = agnosticEvents
|
||||||
|
|
||||||
w.mu.Lock()
|
w.mu.Lock()
|
||||||
watchEntry, found := w.watches[name]
|
defer w.mu.Unlock()
|
||||||
w.mu.Unlock()
|
watchEntry := w.watches[name]
|
||||||
if found {
|
if watchEntry != nil {
|
||||||
watchEntry.flags |= flags
|
flags |= watchEntry.flags | unix.IN_MASK_ADD
|
||||||
flags |= unix.IN_MASK_ADD
|
|
||||||
}
|
}
|
||||||
wd, errno := unix.InotifyAddWatch(w.fd, name, flags)
|
wd, errno := unix.InotifyAddWatch(w.fd, name, flags)
|
||||||
if wd == -1 {
|
if wd == -1 {
|
||||||
return errno
|
return errno
|
||||||
}
|
}
|
||||||
|
|
||||||
w.mu.Lock()
|
if watchEntry == nil {
|
||||||
w.watches[name] = &watch{wd: uint32(wd), flags: flags}
|
w.watches[name] = &watch{wd: uint32(wd), flags: flags}
|
||||||
w.paths[wd] = name
|
w.paths[wd] = name
|
||||||
w.mu.Unlock()
|
} else {
|
||||||
|
watchEntry.wd = uint32(wd)
|
||||||
|
watchEntry.flags = flags
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -135,6 +135,13 @@ func (w *Watcher) Remove(name string) error {
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("can't remove non-existent inotify watch for: %s", name)
|
return fmt.Errorf("can't remove non-existent inotify watch for: %s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We successfully removed the watch if InotifyRmWatch doesn't return an
|
||||||
|
// error, we need to clean up our internal state to ensure it matches
|
||||||
|
// inotify's kernel state.
|
||||||
|
delete(w.paths, int(watch.wd))
|
||||||
|
delete(w.watches, name)
|
||||||
|
|
||||||
// inotify_rm_watch will return EINVAL if the file has been deleted;
|
// inotify_rm_watch will return EINVAL if the file has been deleted;
|
||||||
// the inotify will already have been removed.
|
// the inotify will already have been removed.
|
||||||
// watches and pathes are deleted in ignoreLinux() implicitly and asynchronously
|
// watches and pathes are deleted in ignoreLinux() implicitly and asynchronously
|
||||||
|
@ -152,13 +159,6 @@ func (w *Watcher) Remove(name string) error {
|
||||||
return errno
|
return errno
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait until ignoreLinux() deleting maps
|
|
||||||
exists := true
|
|
||||||
for exists {
|
|
||||||
w.cv.Wait()
|
|
||||||
_, exists = w.watches[name]
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,13 +245,31 @@ func (w *Watcher) readEvents() {
|
||||||
|
|
||||||
mask := uint32(raw.Mask)
|
mask := uint32(raw.Mask)
|
||||||
nameLen := uint32(raw.Len)
|
nameLen := uint32(raw.Len)
|
||||||
|
|
||||||
|
if mask&unix.IN_Q_OVERFLOW != 0 {
|
||||||
|
select {
|
||||||
|
case w.Errors <- ErrEventOverflow:
|
||||||
|
case <-w.done:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the event happened to the watched directory or the watched file, the kernel
|
// If the event happened to the watched directory or the watched file, the kernel
|
||||||
// doesn't append the filename to the event, but we would like to always fill the
|
// doesn't append the filename to the event, but we would like to always fill the
|
||||||
// the "Name" field with a valid filename. We retrieve the path of the watch from
|
// the "Name" field with a valid filename. We retrieve the path of the watch from
|
||||||
// the "paths" map.
|
// the "paths" map.
|
||||||
w.mu.Lock()
|
w.mu.Lock()
|
||||||
name := w.paths[int(raw.Wd)]
|
name, ok := w.paths[int(raw.Wd)]
|
||||||
|
// IN_DELETE_SELF occurs when the file/directory being watched is removed.
|
||||||
|
// This is a sign to clean up the maps, otherwise we are no longer in sync
|
||||||
|
// with the inotify kernel state which has already deleted the watch
|
||||||
|
// automatically.
|
||||||
|
if ok && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF {
|
||||||
|
delete(w.paths, int(raw.Wd))
|
||||||
|
delete(w.watches, name)
|
||||||
|
}
|
||||||
w.mu.Unlock()
|
w.mu.Unlock()
|
||||||
|
|
||||||
if nameLen > 0 {
|
if nameLen > 0 {
|
||||||
// Point "bytes" at the first byte of the filename
|
// Point "bytes" at the first byte of the filename
|
||||||
bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))
|
bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))
|
||||||
|
@ -262,7 +280,7 @@ func (w *Watcher) readEvents() {
|
||||||
event := newEvent(name, mask)
|
event := newEvent(name, mask)
|
||||||
|
|
||||||
// Send the events that are not ignored on the events channel
|
// Send the events that are not ignored on the events channel
|
||||||
if !event.ignoreLinux(w, raw.Wd, mask) {
|
if !event.ignoreLinux(mask) {
|
||||||
select {
|
select {
|
||||||
case w.Events <- event:
|
case w.Events <- event:
|
||||||
case <-w.done:
|
case <-w.done:
|
||||||
|
@ -279,15 +297,9 @@ func (w *Watcher) readEvents() {
|
||||||
// Certain types of events can be "ignored" and not sent over the Events
|
// Certain types of events can be "ignored" and not sent over the Events
|
||||||
// channel. Such as events marked ignore by the kernel, or MODIFY events
|
// channel. Such as events marked ignore by the kernel, or MODIFY events
|
||||||
// against files that do not exist.
|
// against files that do not exist.
|
||||||
func (e *Event) ignoreLinux(w *Watcher, wd int32, mask uint32) bool {
|
func (e *Event) ignoreLinux(mask uint32) bool {
|
||||||
// Ignore anything the inotify API says to ignore
|
// Ignore anything the inotify API says to ignore
|
||||||
if mask&unix.IN_IGNORED == unix.IN_IGNORED {
|
if mask&unix.IN_IGNORED == unix.IN_IGNORED {
|
||||||
w.mu.Lock()
|
|
||||||
defer w.mu.Unlock()
|
|
||||||
name := w.paths[int(wd)]
|
|
||||||
delete(w.paths, int(wd))
|
|
||||||
delete(w.watches, name)
|
|
||||||
w.cv.Broadcast()
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue