From 406b394704c658751d6863bb5d240cc6838c24e2 Mon Sep 17 00:00:00 2001 From: Simon Frei Date: Tue, 26 Jun 2018 10:13:39 +0200 Subject: [PATCH] vendor: Update github.com/syncthing/notify (fixes #4854) (#5032) --- .../syncthing/notify/debug_debug.go | 4 +- .../syncthing/notify/debug_nodebug.go | 4 +- vendor/github.com/syncthing/notify/notify.go | 37 +----- .../syncthing/notify/watcher_fsevents_cgo.go | 6 +- .../syncthing/notify/watcher_readdcw.go | 123 +++++++++++------- .../syncthing/notify/watcher_stub.go | 22 +--- .../syncthing/notify/watcher_trigger.go | 3 +- vendor/manifest | 2 +- 8 files changed, 93 insertions(+), 108 deletions(-) diff --git a/vendor/github.com/syncthing/notify/debug_debug.go b/vendor/github.com/syncthing/notify/debug_debug.go index 6fca891ab..9d234cedd 100644 --- a/vendor/github.com/syncthing/notify/debug_debug.go +++ b/vendor/github.com/syncthing/notify/debug_debug.go @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. +// Copyright (c) 2014-2018 The Notify Authors. All rights reserved. // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. @@ -6,4 +6,4 @@ package notify -var debugTag bool = true +var debugTag = true diff --git a/vendor/github.com/syncthing/notify/debug_nodebug.go b/vendor/github.com/syncthing/notify/debug_nodebug.go index be391a276..9ebf880d8 100644 --- a/vendor/github.com/syncthing/notify/debug_nodebug.go +++ b/vendor/github.com/syncthing/notify/debug_nodebug.go @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. +// Copyright (c) 2014-2018 The Notify Authors. All rights reserved. // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. @@ -6,4 +6,4 @@ package notify -var debugTag bool = false +var debugTag = false diff --git a/vendor/github.com/syncthing/notify/notify.go b/vendor/github.com/syncthing/notify/notify.go index 83ec74199..6f97fc00f 100644 --- a/vendor/github.com/syncthing/notify/notify.go +++ b/vendor/github.com/syncthing/notify/notify.go @@ -19,34 +19,10 @@ package notify -import "fmt" - -var defaultTree tree // lazy init +var defaultTree = newTree() type DoNotWatchFn func(string) bool -func lazyInitDefaultTree() (err error) { - if defaultTree != nil { - // already initialized - return nil - } - - defer func() { - // newTree might panic. Patch it up. - if rec := recover(); rec != nil { - switch rec := rec.(type) { - case error: - err = rec - default: - err = fmt.Errorf("init default tree: %v", rec) - } - } - }() - - defaultTree = newTree() - return nil -} - // Watch sets up a watchpoint on path listening for events given by the events // argument. // @@ -87,9 +63,6 @@ func lazyInitDefaultTree() (err error) { // e.g. use persistent paths like %userprofile% or watch additionally parent // directory of a recursive watchpoint in order to receive delete events for it. func Watch(path string, c chan<- EventInfo, events ...Event) error { - if err := lazyInitDefaultTree(); err != nil { - return err - } return defaultTree.Watch(path, c, nil, events...) } @@ -98,10 +71,7 @@ func Watch(path string, c chan<- EventInfo, events ...Event) error { // doNotWatch. Given a path as argument doNotWatch should return true if the // file or directory should not be watched. func WatchWithFilter(path string, c chan<- EventInfo, - doNotWatch DoNotWatchFn, events ...Event) error { - if err := lazyInitDefaultTree(); err != nil { - return err - } + doNotWatch func(string) bool, events ...Event) error { return defaultTree.Watch(path, c, doNotWatch, events...) } @@ -111,8 +81,5 @@ func WatchWithFilter(path string, c chan<- EventInfo, // Stop does not close c. When Stop returns, it is guaranteed that c will // receive no more signals. func Stop(c chan<- EventInfo) { - if defaultTree == nil { - return - } defaultTree.Stop(c) } diff --git a/vendor/github.com/syncthing/notify/watcher_fsevents_cgo.go b/vendor/github.com/syncthing/notify/watcher_fsevents_cgo.go index a2b332a2e..17f7a9ee9 100644 --- a/vendor/github.com/syncthing/notify/watcher_fsevents_cgo.go +++ b/vendor/github.com/syncthing/notify/watcher_fsevents_cgo.go @@ -90,6 +90,10 @@ func gostream(_, info uintptr, n C.size_t, paths, flags, ids uintptr) { if n == 0 { return } + fn := streamFuncs.get(info) + if fn == nil { + return + } ev := make([]FSEvent, 0, int(n)) for i := uintptr(0); i < uintptr(n); i++ { switch flags := *(*uint32)(unsafe.Pointer((flags + i*offflag))); { @@ -104,7 +108,7 @@ func gostream(_, info uintptr, n C.size_t, paths, flags, ids uintptr) { } } - streamFuncs.get(info)(ev) + fn(ev) } // StreamFunc is a callback called when stream receives file events. diff --git a/vendor/github.com/syncthing/notify/watcher_readdcw.go b/vendor/github.com/syncthing/notify/watcher_readdcw.go index 1494fcd79..b69811a69 100644 --- a/vendor/github.com/syncthing/notify/watcher_readdcw.go +++ b/vendor/github.com/syncthing/notify/watcher_readdcw.go @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. +// Copyright (c) 2014-2018 The Notify Authors. All rights reserved. // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. @@ -22,7 +22,7 @@ import ( const readBufferSize = 4096 // Since all operations which go through the Windows completion routine are done -// asynchronously, filter may set one of the constants belor. They were defined +// asynchronously, filter may set one of the constants below. They were defined // in order to distinguish whether current folder should be re-registered in // ReadDirectoryChangesW function or some control operations need to be executed. const ( @@ -109,8 +109,13 @@ func (g *grip) register(cph syscall.Handle) (err error) { // buffer. Directory changes that occur between calls to this function are added // to the buffer and then, returned with the next call. func (g *grip) readDirChanges() error { + handle := syscall.Handle(atomic.LoadUintptr((*uintptr)(&g.handle))) + if handle == syscall.InvalidHandle { + return nil // Handle was closed. + } + return syscall.ReadDirectoryChanges( - g.handle, + handle, &g.buffer[0], uint32(unsafe.Sizeof(g.buffer)), g.recursive, @@ -220,12 +225,27 @@ func (wd *watched) updateGrip(idx int, cph syscall.Handle, reset bool, // returned from the operating system kernel. func (wd *watched) closeHandle() (err error) { for _, g := range wd.digrip { - if g != nil && g.handle != syscall.InvalidHandle { - switch suberr := syscall.CloseHandle(g.handle); { - case suberr == nil: - g.handle = syscall.InvalidHandle - case err == nil: - err = suberr + if g == nil { + continue + } + + for { + handle := syscall.Handle(atomic.LoadUintptr((*uintptr)(&g.handle))) + if handle == syscall.InvalidHandle { + break // Already closed. + } + + e := syscall.CloseHandle(handle) + if e != nil && err == nil { + err = e + } + + // Set invalid handle even when CloseHandle fails. This will leak + // the handle but, since we can't close it anyway, there won't be + // any difference. + if atomic.CompareAndSwapUintptr((*uintptr)(&g.handle), + (uintptr)(handle), (uintptr)(syscall.InvalidHandle)) { + break } } } @@ -272,50 +292,49 @@ func (r *readdcw) RecursiveWatch(path string, event Event) error { // watch inserts a directory to the group of watched folders. If watched folder // already exists, function tries to rewatch it with new filters(NOT VALID). Moreover, // watch starts the main event loop goroutine when called for the first time. -func (r *readdcw) watch(path string, event Event, recursive bool) (err error) { +func (r *readdcw) watch(path string, event Event, recursive bool) error { if event&^(All|fileNotifyChangeAll) != 0 { return errors.New("notify: unknown event") } + r.Lock() - wd, ok := r.m[path] - r.Unlock() - if !ok { - if err = r.lazyinit(); err != nil { - return - } - r.Lock() - defer r.Unlock() - if wd, ok = r.m[path]; ok { - dbgprint("watch: exists already") - return - } - if wd, err = newWatched(r.cph, uint32(event), recursive, path); err != nil { - return - } - r.m[path] = wd - dbgprint("watch: new watch added") - } else { - dbgprint("watch: exists already") + defer r.Unlock() + + if wd, ok := r.m[path]; ok { + dbgprint("watch: already exists") + wd.filter &^= stateUnwatch + return nil } + + if err := r.lazyinit(); err != nil { + return err + } + + wd, err := newWatched(r.cph, uint32(event), recursive, path) + if err != nil { + return err + } + + r.m[path] = wd + dbgprint("watch: new watch added") + return nil } -// lazyinit creates an I/O completion port and starts the main event processing -// loop. This method uses Double-Checked Locking optimization. +// lazyinit creates an I/O completion port and starts the main event loop. func (r *readdcw) lazyinit() (err error) { invalid := uintptr(syscall.InvalidHandle) + if atomic.LoadUintptr((*uintptr)(&r.cph)) == invalid { - r.Lock() - defer r.Unlock() - if atomic.LoadUintptr((*uintptr)(&r.cph)) == invalid { - cph := syscall.InvalidHandle - if cph, err = syscall.CreateIoCompletionPort(cph, 0, 0, 0); err != nil { - return - } - r.cph, r.start = cph, true - go r.loop() + cph := syscall.InvalidHandle + if cph, err = syscall.CreateIoCompletionPort(cph, 0, 0, 0); err != nil { + return } + + r.cph, r.start = cph, true + go r.loop() } + return } @@ -364,6 +383,7 @@ func (r *readdcw) loopstate(overEx *overlappedEx) { overEx.parent.parent.recreate(r.cph) case stateUnwatch: dbgprint("loopstate unwatch") + overEx.parent.parent.closeHandle() delete(r.m, syscall.UTF16ToString(overEx.parent.pathw)) case stateCPClose: default: @@ -495,27 +515,30 @@ func (r *readdcw) RecursiveUnwatch(path string) error { // TODO : pknap func (r *readdcw) unwatch(path string) (err error) { var wd *watched + r.Lock() defer r.Unlock() if wd, err = r.nonStateWatchedLocked(path); err != nil { return } + wd.filter |= stateUnwatch - if err = wd.closeHandle(); err != nil { - wd.filter &^= stateUnwatch - return - } + dbgprint("unwatch: set unwatch state") + if _, attrErr := syscall.GetFileAttributes(&wd.pathw[0]); attrErr != nil { for _, g := range wd.digrip { - if g != nil { - dbgprint("unwatch: posting") - if err = syscall.PostQueuedCompletionStatus(r.cph, 0, 0, (*syscall.Overlapped)(unsafe.Pointer(g.ovlapped))); err != nil { - wd.filter &^= stateUnwatch - return - } + if g == nil { + continue + } + + dbgprint("unwatch: posting") + if err = syscall.PostQueuedCompletionStatus(r.cph, 0, 0, (*syscall.Overlapped)(unsafe.Pointer(g.ovlapped))); err != nil { + wd.filter &^= stateUnwatch + return } } } + return } diff --git a/vendor/github.com/syncthing/notify/watcher_stub.go b/vendor/github.com/syncthing/notify/watcher_stub.go index 68b9c135b..9b284ddc8 100644 --- a/vendor/github.com/syncthing/notify/watcher_stub.go +++ b/vendor/github.com/syncthing/notify/watcher_stub.go @@ -1,23 +1,13 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. +// Copyright (c) 2014-2018 The Notify Authors. All rights reserved. // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -// +build !darwin,!linux,!freebsd,!dragonfly,!netbsd,!openbsd,!windows -// +build !kqueue,!solaris - package notify -import "errors" - -type stub struct{ error } - -// newWatcher stub. -func newWatcher(chan<- EventInfo) watcher { - return stub{errors.New("notify: not implemented")} -} +type watcherStub struct{ error } // Following methods implement notify.watcher interface. -func (s stub) Watch(string, Event) error { return s } -func (s stub) Rewatch(string, Event, Event) error { return s } -func (s stub) Unwatch(string) (err error) { return s } -func (s stub) Close() error { return s } +func (s watcherStub) Watch(string, Event) error { return s } +func (s watcherStub) Rewatch(string, Event, Event) error { return s } +func (s watcherStub) Unwatch(string) (err error) { return s } +func (s watcherStub) Close() error { return s } diff --git a/vendor/github.com/syncthing/notify/watcher_trigger.go b/vendor/github.com/syncthing/notify/watcher_trigger.go index 78151f909..1ebe04829 100644 --- a/vendor/github.com/syncthing/notify/watcher_trigger.go +++ b/vendor/github.com/syncthing/notify/watcher_trigger.go @@ -106,7 +106,8 @@ func newWatcher(c chan<- EventInfo) watcher { } t.t = newTrigger(t.pthLkp) if err := t.t.Init(); err != nil { - panic(err) + t.Close() + return watcherStub{fmt.Errorf("failed setting up watcher: %v", err)} } go t.monitor() return t diff --git a/vendor/manifest b/vendor/manifest index 7e44df8b9..f3c1b565a 100644 --- a/vendor/manifest +++ b/vendor/manifest @@ -443,7 +443,7 @@ "importpath": "github.com/syncthing/notify", "repository": "https://github.com/syncthing/notify", "vcs": "git", - "revision": "b9ceffc925039c77cd9e0d38f248279ccc4399e2", + "revision": "cdf89c4039d13726e227d0a472053ea19de021b4", "branch": "master", "notests": true },