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
 | 
			
		||||
 | 
			
		||||
# fsnotify
 | 
			
		||||
github.com/fsnotify/fsnotify v1.4.2
 | 
			
		||||
github.com/fsnotify/fsnotify 4da3e2cfbabc9f751898f250b49f2439785783a1
 | 
			
		||||
 | 
			
		||||
# awslogs deps
 | 
			
		||||
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/...
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Cross platform: Windows, Linux, BSD and OS X.
 | 
			
		||||
Cross platform: Windows, Linux, BSD and macOS.
 | 
			
		||||
 | 
			
		||||
|Adapter   |OS        |Status    |
 | 
			
		||||
|----------|----------|----------|
 | 
			
		||||
|inotify   |Linux 2.6.27 or later, Android\*|Supported [](https://travis-ci.org/fsnotify/fsnotify)|
 | 
			
		||||
|kqueue    |BSD, OS X, iOS\*|Supported [](https://travis-ci.org/fsnotify/fsnotify)|
 | 
			
		||||
|kqueue    |BSD, macOS, iOS\*|Supported [](https://travis-ci.org/fsnotify/fsnotify)|
 | 
			
		||||
|ReadDirectoryChangesW|Windows|Supported [](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)|
 | 
			
		||||
|fanotify  |Linux 2.6.37+ | |
 | 
			
		||||
|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.
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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).
 | 
			
		||||
 | 
			
		||||
## 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
 | 
			
		||||
 | 
			
		||||
## 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 (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -60,3 +61,6 @@ func (op Op) String() string {
 | 
			
		|||
func (e Event) String() 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
 | 
			
		||||
	Errors   chan error
 | 
			
		||||
	mu       sync.Mutex // Map access
 | 
			
		||||
	cv       *sync.Cond // sync removing on rm_watch with IN_IGNORE
 | 
			
		||||
	fd       int
 | 
			
		||||
	poller   *fdPoller
 | 
			
		||||
	watches  map[string]*watch // Map of inotify watches (key: path)
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +55,6 @@ func NewWatcher() (*Watcher, error) {
 | 
			
		|||
		done:     make(chan struct{}),
 | 
			
		||||
		doneResp: make(chan struct{}),
 | 
			
		||||
	}
 | 
			
		||||
	w.cv = sync.NewCond(&w.mu)
 | 
			
		||||
 | 
			
		||||
	go w.readEvents()
 | 
			
		||||
	return w, nil
 | 
			
		||||
| 
						 | 
				
			
			@ -103,21 +101,23 @@ func (w *Watcher) Add(name string) error {
 | 
			
		|||
	var flags uint32 = agnosticEvents
 | 
			
		||||
 | 
			
		||||
	w.mu.Lock()
 | 
			
		||||
	watchEntry, found := w.watches[name]
 | 
			
		||||
	w.mu.Unlock()
 | 
			
		||||
	if found {
 | 
			
		||||
		watchEntry.flags |= flags
 | 
			
		||||
		flags |= unix.IN_MASK_ADD
 | 
			
		||||
	defer w.mu.Unlock()
 | 
			
		||||
	watchEntry := w.watches[name]
 | 
			
		||||
	if watchEntry != nil {
 | 
			
		||||
		flags |= watchEntry.flags | unix.IN_MASK_ADD
 | 
			
		||||
	}
 | 
			
		||||
	wd, errno := unix.InotifyAddWatch(w.fd, name, flags)
 | 
			
		||||
	if wd == -1 {
 | 
			
		||||
		return errno
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w.mu.Lock()
 | 
			
		||||
	w.watches[name] = &watch{wd: uint32(wd), flags: flags}
 | 
			
		||||
	w.paths[wd] = name
 | 
			
		||||
	w.mu.Unlock()
 | 
			
		||||
	if watchEntry == nil {
 | 
			
		||||
		w.watches[name] = &watch{wd: uint32(wd), flags: flags}
 | 
			
		||||
		w.paths[wd] = name
 | 
			
		||||
	} else {
 | 
			
		||||
		watchEntry.wd = uint32(wd)
 | 
			
		||||
		watchEntry.flags = flags
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -135,6 +135,13 @@ func (w *Watcher) Remove(name string) error {
 | 
			
		|||
	if !ok {
 | 
			
		||||
		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;
 | 
			
		||||
	// the inotify will already have been removed.
 | 
			
		||||
	// watches and pathes are deleted in ignoreLinux() implicitly and asynchronously
 | 
			
		||||
| 
						 | 
				
			
			@ -152,13 +159,6 @@ func (w *Watcher) Remove(name string) error {
 | 
			
		|||
		return errno
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// wait until ignoreLinux() deleting maps
 | 
			
		||||
	exists := true
 | 
			
		||||
	for exists {
 | 
			
		||||
		w.cv.Wait()
 | 
			
		||||
		_, exists = w.watches[name]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -245,13 +245,31 @@ func (w *Watcher) readEvents() {
 | 
			
		|||
 | 
			
		||||
			mask := uint32(raw.Mask)
 | 
			
		||||
			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
 | 
			
		||||
			// 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 "paths" map.
 | 
			
		||||
			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()
 | 
			
		||||
 | 
			
		||||
			if nameLen > 0 {
 | 
			
		||||
				// Point "bytes" at the first byte of the filename
 | 
			
		||||
				bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))
 | 
			
		||||
| 
						 | 
				
			
			@ -262,7 +280,7 @@ func (w *Watcher) readEvents() {
 | 
			
		|||
			event := newEvent(name, mask)
 | 
			
		||||
 | 
			
		||||
			// Send the events that are not ignored on the events channel
 | 
			
		||||
			if !event.ignoreLinux(w, raw.Wd, mask) {
 | 
			
		||||
			if !event.ignoreLinux(mask) {
 | 
			
		||||
				select {
 | 
			
		||||
				case w.Events <- event:
 | 
			
		||||
				case <-w.done:
 | 
			
		||||
| 
						 | 
				
			
			@ -279,15 +297,9 @@ func (w *Watcher) readEvents() {
 | 
			
		|||
// 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
 | 
			
		||||
// 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
 | 
			
		||||
	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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue