diff options
Diffstat (limited to 'vendor/github.com/rjeczalik')
19 files changed, 231 insertions, 157 deletions
diff --git a/vendor/github.com/rjeczalik/notify/README.md b/vendor/github.com/rjeczalik/notify/README.md index a728d1dd0..02a5f3290 100644 --- a/vendor/github.com/rjeczalik/notify/README.md +++ b/vendor/github.com/rjeczalik/notify/README.md @@ -18,4 +18,4 @@ Filesystem event notification library on steroids. (under active development) - [github.com/rjeczalik/cmd/notify](https://godoc.org/github.com/rjeczalik/cmd/notify) - [github.com/cortesi/devd](https://github.com/cortesi/devd) - [github.com/cortesi/modd](https://github.com/cortesi/modd) - +- [github.com/syncthing/syncthing-inotify](https://github.com/syncthing/syncthing-inotify) diff --git a/vendor/github.com/rjeczalik/notify/appveyor.yml b/vendor/github.com/rjeczalik/notify/appveyor.yml index 8e762d05c..a495bd7c7 100644 --- a/vendor/github.com/rjeczalik/notify/appveyor.yml +++ b/vendor/github.com/rjeczalik/notify/appveyor.yml @@ -16,7 +16,7 @@ install: build_script: - go tool vet -all . - go build ./... - - go test -v -race ./... + - go test -v -timeout 60s -race ./... test: off diff --git a/vendor/github.com/rjeczalik/notify/debug.go b/vendor/github.com/rjeczalik/notify/debug.go index bd9bc468d..2a3eb3370 100644 --- a/vendor/github.com/rjeczalik/notify/debug.go +++ b/vendor/github.com/rjeczalik/notify/debug.go @@ -2,10 +2,52 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -// +build !debug - package notify -func dbgprint(...interface{}) {} +import ( + "log" + "os" + "runtime" + "strings" +) + +var dbgprint func(...interface{}) + +var dbgprintf func(string, ...interface{}) + +var dbgcallstack func(max int) []string -func dbgprintf(string, ...interface{}) {} +func init() { + if _, ok := os.LookupEnv("NOTIFY_DEBUG"); ok || debugTag { + log.SetOutput(os.Stdout) + log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds) + dbgprint = func(v ...interface{}) { + v = append([]interface{}{"[D] "}, v...) + log.Println(v...) + } + dbgprintf = func(format string, v ...interface{}) { + format = "[D] " + format + log.Printf(format, v...) + } + dbgcallstack = func(max int) []string { + pc, stack := make([]uintptr, max), make([]string, 0, max) + runtime.Callers(2, pc) + for _, pc := range pc { + if f := runtime.FuncForPC(pc); f != nil { + fname := f.Name() + idx := strings.LastIndex(fname, string(os.PathSeparator)) + if idx != -1 { + stack = append(stack, fname[idx+1:]) + } else { + stack = append(stack, fname) + } + } + } + return stack + } + return + } + dbgprint = func(v ...interface{}) {} + dbgprintf = func(format string, v ...interface{}) {} + dbgcallstack = func(max int) []string { return nil } +} diff --git a/vendor/github.com/rjeczalik/notify/debug_debug.go b/vendor/github.com/rjeczalik/notify/debug_debug.go index f0622917f..6fca891ab 100644 --- a/vendor/github.com/rjeczalik/notify/debug_debug.go +++ b/vendor/github.com/rjeczalik/notify/debug_debug.go @@ -6,38 +6,4 @@ package notify -import ( - "fmt" - "os" - "runtime" - "strings" -) - -func dbgprint(v ...interface{}) { - fmt.Printf("[D] ") - fmt.Print(v...) - fmt.Printf("\n\n") -} - -func dbgprintf(format string, v ...interface{}) { - fmt.Printf("[D] ") - fmt.Printf(format, v...) - fmt.Printf("\n\n") -} - -func dbgcallstack(max int) []string { - pc, stack := make([]uintptr, max), make([]string, 0, max) - runtime.Callers(2, pc) - for _, pc := range pc { - if f := runtime.FuncForPC(pc); f != nil { - fname := f.Name() - idx := strings.LastIndex(fname, string(os.PathSeparator)) - if idx != -1 { - stack = append(stack, fname[idx+1:]) - } else { - stack = append(stack, fname) - } - } - } - return stack -} +var debugTag bool = true diff --git a/vendor/github.com/rjeczalik/notify/debug_nodebug.go b/vendor/github.com/rjeczalik/notify/debug_nodebug.go new file mode 100644 index 000000000..be391a276 --- /dev/null +++ b/vendor/github.com/rjeczalik/notify/debug_nodebug.go @@ -0,0 +1,9 @@ +// Copyright (c) 2014-2015 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 !debug + +package notify + +var debugTag bool = false diff --git a/vendor/github.com/rjeczalik/notify/doc.go b/vendor/github.com/rjeczalik/notify/doc.go index 8a99ddda6..60543c083 100644 --- a/vendor/github.com/rjeczalik/notify/doc.go +++ b/vendor/github.com/rjeczalik/notify/doc.go @@ -12,11 +12,14 @@ // source file. // // On top of filesystem watchers notify maintains a watchpoint tree, which provides -// strategy for creating and closing filesystem watches and dispatching filesystem +// a strategy for creating and closing filesystem watches and dispatching filesystem // events to user channels. // // An event set is just an event list joint using bitwise OR operator // into a single event value. +// Both the platform-independent (see Constants) and specific events can be used. +// Refer to the event_*.go source files for information about the available +// events. // // A filesystem watch or just a watch is platform-specific entity which represents // a single path registered for notifications for specific event set. Setting a watch @@ -35,6 +38,6 @@ // A watchpoint is a list of user channel and event set pairs for particular // path (watchpoint tree's node). A single watchpoint can contain multiple // different user channels registered to listen for one or more events. A single -// user channel can be registered in one or more watchpoints, recurisve and +// user channel can be registered in one or more watchpoints, recursive and // non-recursive ones as well. package notify diff --git a/vendor/github.com/rjeczalik/notify/event.go b/vendor/github.com/rjeczalik/notify/event.go index e045edcec..c12884197 100644 --- a/vendor/github.com/rjeczalik/notify/event.go +++ b/vendor/github.com/rjeczalik/notify/event.go @@ -73,7 +73,7 @@ func (e Event) String() string { // // https://developer.apple.com/library/mac/documentation/Darwin/Reference/FSEvents_Ref/index.html#//apple_ref/doc/constant_group/FSEventStreamEventFlags // -// Under Linux (inotify) Sys() always returns a non-nil *syscall.InotifyEvent +// Under Linux (inotify) Sys() always returns a non-nil *unix.InotifyEvent // value, defined as: // // type InotifyEvent struct { diff --git a/vendor/github.com/rjeczalik/notify/event_inotify.go b/vendor/github.com/rjeczalik/notify/event_inotify.go index 82954a9b3..1f32bb73e 100644 --- a/vendor/github.com/rjeczalik/notify/event_inotify.go +++ b/vendor/github.com/rjeczalik/notify/event_inotify.go @@ -6,7 +6,7 @@ package notify -import "syscall" +import "golang.org/x/sys/unix" // Platform independent event values. const ( @@ -25,18 +25,18 @@ const ( // Inotify specific masks are legal, implemented events that are guaranteed to // work with notify package on linux-based systems. const ( - InAccess = Event(syscall.IN_ACCESS) // File was accessed - InModify = Event(syscall.IN_MODIFY) // File was modified - InAttrib = Event(syscall.IN_ATTRIB) // Metadata changed - InCloseWrite = Event(syscall.IN_CLOSE_WRITE) // Writtable file was closed - InCloseNowrite = Event(syscall.IN_CLOSE_NOWRITE) // Unwrittable file closed - InOpen = Event(syscall.IN_OPEN) // File was opened - InMovedFrom = Event(syscall.IN_MOVED_FROM) // File was moved from X - InMovedTo = Event(syscall.IN_MOVED_TO) // File was moved to Y - InCreate = Event(syscall.IN_CREATE) // Subfile was created - InDelete = Event(syscall.IN_DELETE) // Subfile was deleted - InDeleteSelf = Event(syscall.IN_DELETE_SELF) // Self was deleted - InMoveSelf = Event(syscall.IN_MOVE_SELF) // Self was moved + InAccess = Event(unix.IN_ACCESS) // File was accessed + InModify = Event(unix.IN_MODIFY) // File was modified + InAttrib = Event(unix.IN_ATTRIB) // Metadata changed + InCloseWrite = Event(unix.IN_CLOSE_WRITE) // Writtable file was closed + InCloseNowrite = Event(unix.IN_CLOSE_NOWRITE) // Unwrittable file closed + InOpen = Event(unix.IN_OPEN) // File was opened + InMovedFrom = Event(unix.IN_MOVED_FROM) // File was moved from X + InMovedTo = Event(unix.IN_MOVED_TO) // File was moved to Y + InCreate = Event(unix.IN_CREATE) // Subfile was created + InDelete = Event(unix.IN_DELETE) // Subfile was deleted + InDeleteSelf = Event(unix.IN_DELETE_SELF) // Self was deleted + InMoveSelf = Event(unix.IN_MOVE_SELF) // Self was moved ) var osestr = map[Event]string{ @@ -56,15 +56,15 @@ var osestr = map[Event]string{ // Inotify behavior events are not **currently** supported by notify package. const ( - inDontFollow = Event(syscall.IN_DONT_FOLLOW) - inExclUnlink = Event(syscall.IN_EXCL_UNLINK) - inMaskAdd = Event(syscall.IN_MASK_ADD) - inOneshot = Event(syscall.IN_ONESHOT) - inOnlydir = Event(syscall.IN_ONLYDIR) + inDontFollow = Event(unix.IN_DONT_FOLLOW) + inExclUnlink = Event(unix.IN_EXCL_UNLINK) + inMaskAdd = Event(unix.IN_MASK_ADD) + inOneshot = Event(unix.IN_ONESHOT) + inOnlydir = Event(unix.IN_ONLYDIR) ) type event struct { - sys syscall.InotifyEvent + sys unix.InotifyEvent path string event Event } @@ -72,4 +72,4 @@ type event struct { func (e *event) Event() Event { return e.event } func (e *event) Path() string { return e.path } func (e *event) Sys() interface{} { return &e.sys } -func (e *event) isDir() (bool, error) { return e.sys.Mask&syscall.IN_ISDIR != 0, nil } +func (e *event) isDir() (bool, error) { return e.sys.Mask&unix.IN_ISDIR != 0, nil } diff --git a/vendor/github.com/rjeczalik/notify/event_readdcw.go b/vendor/github.com/rjeczalik/notify/event_readdcw.go index 11ead9e29..f7b82de0c 100644 --- a/vendor/github.com/rjeczalik/notify/event_readdcw.go +++ b/vendor/github.com/rjeczalik/notify/event_readdcw.go @@ -27,7 +27,11 @@ const ( dirmarker ) -// ReadDirectoryChangesW filters. +// ReadDirectoryChangesW filters +// On Windows the following events can be passed to Watch. A different set of +// events (see actions below) are received on the channel passed to Watch. +// For more information refer to +// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx const ( FileNotifyChangeFileName = Event(syscall.FILE_NOTIFY_CHANGE_FILE_NAME) FileNotifyChangeDirName = Event(syscall.FILE_NOTIFY_CHANGE_DIR_NAME) @@ -48,7 +52,13 @@ const ( // this flag should be declared in: http://golang.org/src/pkg/syscall/ztypes_windows.go const syscallFileNotifyChangeSecurity = 0x00000100 -// ReadDirectoryChangesW actions. +// ReadDirectoryChangesW actions +// The following events are returned on the channel passed to Watch, but cannot +// be passed to Watch itself (see filters above). You can find a table showing +// the relation between actions and filteres at +// https://github.com/rjeczalik/notify/issues/10#issuecomment-66179535 +// The msdn documentation on actions is part of +// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364391(v=vs.85).aspx const ( FileActionAdded = Event(syscall.FILE_ACTION_ADDED) << 12 FileActionRemoved = Event(syscall.FILE_ACTION_REMOVED) << 12 diff --git a/vendor/github.com/rjeczalik/notify/node.go b/vendor/github.com/rjeczalik/notify/node.go index 29c1bb20a..aced8b9c4 100644 --- a/vendor/github.com/rjeczalik/notify/node.go +++ b/vendor/github.com/rjeczalik/notify/node.go @@ -6,7 +6,6 @@ package notify import ( "errors" - "fmt" "io/ioutil" "os" "path/filepath" @@ -71,7 +70,11 @@ Traverse: case errSkip: continue Traverse default: - return fmt.Errorf("error while traversing %q: %v", nd.Name, err) + return &os.PathError{ + Op: "error while traversing", + Path: nd.Name, + Err: err, + } } // TODO(rjeczalik): tolerate open failures - add failed names to // AddDirError and notify users which names are not added to the tree. diff --git a/vendor/github.com/rjeczalik/notify/watcher_fen.go b/vendor/github.com/rjeczalik/notify/watcher_fen.go index dd069f2a2..dfe77f2f1 100644 --- a/vendor/github.com/rjeczalik/notify/watcher_fen.go +++ b/vendor/github.com/rjeczalik/notify/watcher_fen.go @@ -33,14 +33,7 @@ type fen struct { // watched is a data structure representing watched file/directory. type watched struct { - // p is a path to watched file/directory - p string - // fi provides information about watched file/dir - fi os.FileInfo - // eDir represents events watched directly - eDir Event - // eNonDir represents events watched indirectly - eNonDir Event + trgWatched } // Stop implements trigger. @@ -55,7 +48,7 @@ func (f *fen) Close() (err error) { // NewWatched implements trigger. func (*fen) NewWatched(p string, fi os.FileInfo) (*watched, error) { - return &watched{p: p, fi: fi}, nil + return &watched{trgWatched{p: p, fi: fi}}, nil } // Record implements trigger. diff --git a/vendor/github.com/rjeczalik/notify/watcher_fsevents.go b/vendor/github.com/rjeczalik/notify/watcher_fsevents.go index 9062c17c7..7d9b97b65 100644 --- a/vendor/github.com/rjeczalik/notify/watcher_fsevents.go +++ b/vendor/github.com/rjeczalik/notify/watcher_fsevents.go @@ -12,8 +12,6 @@ import ( "sync/atomic" ) -// TODO(rjeczalik): get rid of calls to canonical, it's tree responsibility - const ( failure = uint32(FSEventsMustScanSubDirs | FSEventsUserDropped | FSEventsKernelDropped) filter = uint32(FSEventsCreated | FSEventsRemoved | FSEventsRenamed | @@ -189,9 +187,6 @@ func newWatcher(c chan<- EventInfo) watcher { } func (fse *fsevents) watch(path string, event Event, isrec int32) (err error) { - if path, err = canonical(path); err != nil { - return err - } if _, ok := fse.watches[path]; ok { return errAlreadyWatched } @@ -211,9 +206,6 @@ func (fse *fsevents) watch(path string, event Event, isrec int32) (err error) { } func (fse *fsevents) unwatch(path string) (err error) { - if path, err = canonical(path); err != nil { - return - } w, ok := fse.watches[path] if !ok { return errNotWatched diff --git a/vendor/github.com/rjeczalik/notify/watcher_fsevents_cgo.go b/vendor/github.com/rjeczalik/notify/watcher_fsevents_cgo.go index 5be64632e..2248a1b12 100644 --- a/vendor/github.com/rjeczalik/notify/watcher_fsevents_cgo.go +++ b/vendor/github.com/rjeczalik/notify/watcher_fsevents_cgo.go @@ -26,9 +26,9 @@ import "C" import ( "errors" "os" + "runtime" "sync" "sync/atomic" - "time" "unsafe" ) @@ -48,7 +48,7 @@ var wg sync.WaitGroup // used to wait until the runloop starts // started and is ready via the wg. It also serves purpose of a dummy source, // thanks to it the runloop does not return as it also has at least one source // registered. -var source = C.CFRunLoopSourceCreate(nil, 0, &C.CFRunLoopSourceContext{ +var source = C.CFRunLoopSourceCreate(refZero, 0, &C.CFRunLoopSourceContext{ perform: (C.CFRunLoopPerformCallBack)(C.gosource), }) @@ -63,6 +63,10 @@ var ( func init() { wg.Add(1) go func() { + // There is exactly one run loop per thread. Lock this goroutine to its + // thread to ensure that it's not rescheduled on a different thread while + // setting up the run loop. + runtime.LockOSThread() runloop = C.CFRunLoopGetCurrent() C.CFRunLoopAddSource(runloop, source, C.kCFRunLoopDefaultMode) C.CFRunLoopRun() @@ -73,7 +77,6 @@ func init() { //export gosource func gosource(unsafe.Pointer) { - time.Sleep(time.Second) wg.Done() } @@ -159,8 +162,8 @@ func (s *stream) Start() error { return nil } wg.Wait() - p := C.CFStringCreateWithCStringNoCopy(nil, C.CString(s.path), C.kCFStringEncodingUTF8, nil) - path := C.CFArrayCreate(nil, (*unsafe.Pointer)(unsafe.Pointer(&p)), 1, nil) + p := C.CFStringCreateWithCStringNoCopy(refZero, C.CString(s.path), C.kCFStringEncodingUTF8, refZero) + path := C.CFArrayCreate(refZero, (*unsafe.Pointer)(unsafe.Pointer(&p)), 1, nil) ctx := C.FSEventStreamContext{} ref := C.EventStreamCreate(&ctx, C.uintptr_t(s.info), path, C.FSEventStreamEventId(atomic.LoadUint64(&since)), latency, flags) if ref == nilstream { diff --git a/vendor/github.com/rjeczalik/notify/watcher_fsevents_go1.10.go b/vendor/github.com/rjeczalik/notify/watcher_fsevents_go1.10.go new file mode 100644 index 000000000..0edd3782f --- /dev/null +++ b/vendor/github.com/rjeczalik/notify/watcher_fsevents_go1.10.go @@ -0,0 +1,9 @@ +// Copyright (c) 2017 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,!kqueue,go1.10 + +package notify + +const refZero = 0 diff --git a/vendor/github.com/rjeczalik/notify/watcher_fsevents_go1.9.go b/vendor/github.com/rjeczalik/notify/watcher_fsevents_go1.9.go new file mode 100644 index 000000000..b81c3c185 --- /dev/null +++ b/vendor/github.com/rjeczalik/notify/watcher_fsevents_go1.9.go @@ -0,0 +1,14 @@ +// Copyright (c) 2017 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,!kqueue,cgo,!go1.10 + +package notify + +/* +#include <CoreServices/CoreServices.h> +*/ +import "C" + +var refZero = (*C.struct___CFAllocator)(nil) diff --git a/vendor/github.com/rjeczalik/notify/watcher_inotify.go b/vendor/github.com/rjeczalik/notify/watcher_inotify.go index 3ceaa8f3a..d082baca0 100644 --- a/vendor/github.com/rjeczalik/notify/watcher_inotify.go +++ b/vendor/github.com/rjeczalik/notify/watcher_inotify.go @@ -13,14 +13,15 @@ import ( "runtime" "sync" "sync/atomic" - "syscall" "unsafe" + + "golang.org/x/sys/unix" ) // eventBufferSize defines the size of the buffer given to read(2) function. One // should not depend on this value, since it was arbitrary chosen and may be // changed in the future. -const eventBufferSize = 64 * (syscall.SizeofInotifyEvent + syscall.PathMax + 1) +const eventBufferSize = 64 * (unix.SizeofInotifyEvent + unix.PathMax + 1) // consumersCount defines the number of consumers in producer-consumer based // implementation. Each consumer is run in a separate goroutine and has read @@ -43,7 +44,7 @@ type inotify struct { fd int32 // inotify file descriptor pipefd []int // pipe's read and write descriptors epfd int // epoll descriptor - epes []syscall.EpollEvent // epoll events + epes []unix.EpollEvent // epoll events buffer [eventBufferSize]byte // inotify event buffer wg sync.WaitGroup // wait group used to close main loop c chan<- EventInfo // event dispatcher channel @@ -56,13 +57,13 @@ func newWatcher(c chan<- EventInfo) watcher { fd: invalidDescriptor, pipefd: []int{invalidDescriptor, invalidDescriptor}, epfd: invalidDescriptor, - epes: make([]syscall.EpollEvent, 0), + epes: make([]unix.EpollEvent, 0), c: c, } runtime.SetFinalizer(i, func(i *inotify) { i.epollclose() if i.fd != invalidDescriptor { - syscall.Close(int(i.fd)) + unix.Close(int(i.fd)) } }) return i @@ -82,13 +83,13 @@ func (i *inotify) Rewatch(path string, _, newevent Event) error { // one. If called for the first time, this function initializes inotify filesystem // monitor and starts producer-consumers goroutines. func (i *inotify) watch(path string, e Event) (err error) { - if e&^(All|Event(syscall.IN_ALL_EVENTS)) != 0 { + if e&^(All|Event(unix.IN_ALL_EVENTS)) != 0 { return errors.New("notify: unknown event") } if err = i.lazyinit(); err != nil { return } - iwd, err := syscall.InotifyAddWatch(int(i.fd), path, encode(e)) + iwd, err := unix.InotifyAddWatch(int(i.fd), path, encode(e)) if err != nil { return } @@ -119,13 +120,13 @@ func (i *inotify) lazyinit() error { i.Lock() defer i.Unlock() if atomic.LoadInt32(&i.fd) == invalidDescriptor { - fd, err := syscall.InotifyInit() + fd, err := unix.InotifyInit1(unix.IN_CLOEXEC) if err != nil { return err } i.fd = int32(fd) if err = i.epollinit(); err != nil { - _, _ = i.epollclose(), syscall.Close(int(fd)) // Ignore errors. + _, _ = i.epollclose(), unix.Close(int(fd)) // Ignore errors. i.fd = invalidDescriptor return err } @@ -145,33 +146,33 @@ func (i *inotify) lazyinit() error { // with inotify event queue and the read end of the pipe are added to epoll set. // Note that `fd` member must be set before this function is called. func (i *inotify) epollinit() (err error) { - if i.epfd, err = syscall.EpollCreate1(0); err != nil { + if i.epfd, err = unix.EpollCreate1(0); err != nil { return } - if err = syscall.Pipe(i.pipefd); err != nil { + if err = unix.Pipe(i.pipefd); err != nil { return } - i.epes = []syscall.EpollEvent{ - {Events: syscall.EPOLLIN, Fd: i.fd}, - {Events: syscall.EPOLLIN, Fd: int32(i.pipefd[0])}, + i.epes = []unix.EpollEvent{ + {Events: unix.EPOLLIN, Fd: i.fd}, + {Events: unix.EPOLLIN, Fd: int32(i.pipefd[0])}, } - if err = syscall.EpollCtl(i.epfd, syscall.EPOLL_CTL_ADD, int(i.fd), &i.epes[0]); err != nil { + if err = unix.EpollCtl(i.epfd, unix.EPOLL_CTL_ADD, int(i.fd), &i.epes[0]); err != nil { return } - return syscall.EpollCtl(i.epfd, syscall.EPOLL_CTL_ADD, i.pipefd[0], &i.epes[1]) + return unix.EpollCtl(i.epfd, unix.EPOLL_CTL_ADD, i.pipefd[0], &i.epes[1]) } // epollclose closes the file descriptor created by the call to epoll_create(2) // and two file descriptors opened by pipe(2) function. func (i *inotify) epollclose() (err error) { if i.epfd != invalidDescriptor { - if err = syscall.Close(i.epfd); err == nil { + if err = unix.Close(i.epfd); err == nil { i.epfd = invalidDescriptor } } for n, fd := range i.pipefd { if fd != invalidDescriptor { - switch e := syscall.Close(fd); { + switch e := unix.Close(fd); { case e != nil && err == nil: err = e case e == nil: @@ -187,10 +188,10 @@ func (i *inotify) epollclose() (err error) { // one of the event's consumers. If pipe fd became ready, loop function closes // all file descriptors opened by lazyinit method and returns afterwards. func (i *inotify) loop(esch chan<- []*event) { - epes := make([]syscall.EpollEvent, 1) + epes := make([]unix.EpollEvent, 1) fd := atomic.LoadInt32(&i.fd) for { - switch _, err := syscall.EpollWait(i.epfd, epes, -1); err { + switch _, err := unix.EpollWait(i.epfd, epes, -1); err { case nil: switch epes[0].Fd { case fd: @@ -199,17 +200,17 @@ func (i *inotify) loop(esch chan<- []*event) { case int32(i.pipefd[0]): i.Lock() defer i.Unlock() - if err = syscall.Close(int(fd)); err != nil && err != syscall.EINTR { + if err = unix.Close(int(fd)); err != nil && err != unix.EINTR { panic("notify: close(2) error " + err.Error()) } atomic.StoreInt32(&i.fd, invalidDescriptor) - if err = i.epollclose(); err != nil && err != syscall.EINTR { + if err = i.epollclose(); err != nil && err != unix.EINTR { panic("notify: epollclose error " + err.Error()) } close(esch) return } - case syscall.EINTR: + case unix.EINTR: continue default: // We should never reach this line. panic("notify: epoll_wait(2) error " + err.Error()) @@ -220,22 +221,22 @@ func (i *inotify) loop(esch chan<- []*event) { // read reads events from an inotify file descriptor. It does not handle errors // returned from read(2) function since they are not critical to watcher logic. func (i *inotify) read() (es []*event) { - n, err := syscall.Read(int(i.fd), i.buffer[:]) - if err != nil || n < syscall.SizeofInotifyEvent { + n, err := unix.Read(int(i.fd), i.buffer[:]) + if err != nil || n < unix.SizeofInotifyEvent { return } - var sys *syscall.InotifyEvent - nmin := n - syscall.SizeofInotifyEvent + var sys *unix.InotifyEvent + nmin := n - unix.SizeofInotifyEvent for pos, path := 0, ""; pos <= nmin; { - sys = (*syscall.InotifyEvent)(unsafe.Pointer(&i.buffer[pos])) - pos += syscall.SizeofInotifyEvent + sys = (*unix.InotifyEvent)(unsafe.Pointer(&i.buffer[pos])) + pos += unix.SizeofInotifyEvent if path = ""; sys.Len > 0 { endpos := pos + int(sys.Len) path = string(bytes.TrimRight(i.buffer[pos:endpos], "\x00")) pos = endpos } es = append(es, &event{ - sys: syscall.InotifyEvent{ + sys: unix.InotifyEvent{ Wd: sys.Wd, Mask: sys.Mask, Cookie: sys.Cookie, @@ -268,7 +269,7 @@ func (i *inotify) transform(es []*event) []*event { var multi []*event i.RLock() for idx, e := range es { - if e.sys.Mask&(syscall.IN_IGNORED|syscall.IN_Q_OVERFLOW) != 0 { + if e.sys.Mask&(unix.IN_IGNORED|unix.IN_Q_OVERFLOW) != 0 { es[idx] = nil continue } @@ -317,7 +318,7 @@ func encode(e Event) uint32 { // can be nil when the event should not be passed on. func decode(mask Event, e *event) (syse *event) { if sysmask := uint32(mask) & e.sys.Mask; sysmask != 0 { - syse = &event{sys: syscall.InotifyEvent{ + syse = &event{sys: unix.InotifyEvent{ Wd: e.sys.Wd, Mask: e.sys.Mask, Cookie: e.sys.Cookie, @@ -357,7 +358,7 @@ func (i *inotify) Unwatch(path string) (err error) { return errors.New("notify: path " + path + " is already watched") } fd := atomic.LoadInt32(&i.fd) - if _, err = syscall.InotifyRmWatch(int(fd), uint32(iwd)); err != nil { + if err = removeInotifyWatch(fd, iwd); err != nil { return } i.Lock() @@ -377,12 +378,12 @@ func (i *inotify) Close() (err error) { return nil } for iwd := range i.m { - if _, e := syscall.InotifyRmWatch(int(i.fd), uint32(iwd)); e != nil && err == nil { + if e := removeInotifyWatch(i.fd, iwd); e != nil && err == nil { err = e } delete(i.m, iwd) } - switch _, errwrite := syscall.Write(i.pipefd[1], []byte{0x00}); { + switch _, errwrite := unix.Write(i.pipefd[1], []byte{0x00}); { case errwrite != nil && err == nil: err = errwrite fallthrough @@ -394,3 +395,11 @@ func (i *inotify) Close() (err error) { } return } + +// if path was removed, notify already removed the watch and returns EINVAL error +func removeInotifyWatch(fd int32, iwd int32) (err error) { + if _, err = unix.InotifyRmWatch(int(fd), uint32(iwd)); err != nil && err != unix.EINVAL { + return + } + return nil +} diff --git a/vendor/github.com/rjeczalik/notify/watcher_kqueue.go b/vendor/github.com/rjeczalik/notify/watcher_kqueue.go index 6d500b700..22e3c2c4a 100644 --- a/vendor/github.com/rjeczalik/notify/watcher_kqueue.go +++ b/vendor/github.com/rjeczalik/notify/watcher_kqueue.go @@ -36,16 +36,9 @@ type kq struct { // watched is a data structure representing watched file/directory. type watched struct { - // p is a path to watched file/directory. - p string + trgWatched // fd is a file descriptor for watched file/directory. fd int - // fi provides information about watched file/dir. - fi os.FileInfo - // eDir represents events watched directly. - eDir Event - // eNonDir represents events watched indirectly. - eNonDir Event } // Stop implements trigger. @@ -66,7 +59,10 @@ func (*kq) NewWatched(p string, fi os.FileInfo) (*watched, error) { if err != nil { return nil, err } - return &watched{fd: fd, p: p, fi: fi}, nil + return &watched{ + trgWatched: trgWatched{p: p, fi: fi}, + fd: fd, + }, nil } // Record implements trigger. diff --git a/vendor/github.com/rjeczalik/notify/watcher_readdcw.go b/vendor/github.com/rjeczalik/notify/watcher_readdcw.go index 5923bfdda..1494fcd79 100644 --- a/vendor/github.com/rjeczalik/notify/watcher_readdcw.go +++ b/vendor/github.com/rjeczalik/notify/watcher_readdcw.go @@ -284,16 +284,18 @@ func (r *readdcw) watch(path string, event Event, recursive bool) (err error) { return } r.Lock() + defer r.Unlock() if wd, ok = r.m[path]; ok { - r.Unlock() + dbgprint("watch: exists already") return } if wd, err = newWatched(r.cph, uint32(event), recursive, path); err != nil { - r.Unlock() return } r.m[path] = wd - r.Unlock() + dbgprint("watch: new watch added") + } else { + dbgprint("watch: exists already") } return nil } @@ -337,33 +339,32 @@ func (r *readdcw) loop() { continue } overEx := (*overlappedEx)(unsafe.Pointer(overlapped)) - if n == 0 { - r.loopstate(overEx) - } else { + if n != 0 { r.loopevent(n, overEx) if err = overEx.parent.readDirChanges(); err != nil { // TODO: error handling } } + r.loopstate(overEx) } } // TODO(pknap) : doc func (r *readdcw) loopstate(overEx *overlappedEx) { - filter := atomic.LoadUint32(&overEx.parent.parent.filter) + r.Lock() + defer r.Unlock() + filter := overEx.parent.parent.filter if filter&onlyMachineStates == 0 { return } if overEx.parent.parent.count--; overEx.parent.parent.count == 0 { switch filter & onlyMachineStates { case stateRewatch: - r.Lock() + dbgprint("loopstate rewatch") overEx.parent.parent.recreate(r.cph) - r.Unlock() case stateUnwatch: - r.Lock() + dbgprint("loopstate unwatch") delete(r.m, syscall.UTF16ToString(overEx.parent.pathw)) - r.Unlock() case stateCPClose: default: panic(`notify: windows loopstate logic error`) @@ -450,8 +451,8 @@ func (r *readdcw) rewatch(path string, oldevent, newevent uint32, recursive bool } var wd *watched r.Lock() - if wd, err = r.nonStateWatched(path); err != nil { - r.Unlock() + defer r.Unlock() + if wd, err = r.nonStateWatchedLocked(path); err != nil { return } if wd.filter&(onlyNotifyChanges|onlyNGlobalEvents) != oldevent { @@ -462,21 +463,19 @@ func (r *readdcw) rewatch(path string, oldevent, newevent uint32, recursive bool if err = wd.closeHandle(); err != nil { wd.filter = oldevent wd.recursive = recursive - r.Unlock() return } - r.Unlock() return } // TODO : pknap -func (r *readdcw) nonStateWatched(path string) (wd *watched, err error) { +func (r *readdcw) nonStateWatchedLocked(path string) (wd *watched, err error) { wd, ok := r.m[path] if !ok || wd == nil { err = errors.New(`notify: ` + path + ` path is unwatched`) return } - if filter := atomic.LoadUint32(&wd.filter); filter&onlyMachineStates != 0 { + if wd.filter&onlyMachineStates != 0 { err = errors.New(`notify: another re/unwatching operation in progress`) return } @@ -497,17 +496,26 @@ func (r *readdcw) RecursiveUnwatch(path string) error { func (r *readdcw) unwatch(path string) (err error) { var wd *watched r.Lock() - if wd, err = r.nonStateWatched(path); err != nil { - r.Unlock() + defer r.Unlock() + if wd, err = r.nonStateWatchedLocked(path); err != nil { return } wd.filter |= stateUnwatch if err = wd.closeHandle(); err != nil { wd.filter &^= stateUnwatch - r.Unlock() return } - r.Unlock() + 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 + } + } + } + } return } diff --git a/vendor/github.com/rjeczalik/notify/watcher_trigger.go b/vendor/github.com/rjeczalik/notify/watcher_trigger.go index d079d59b0..78151f909 100644 --- a/vendor/github.com/rjeczalik/notify/watcher_trigger.go +++ b/vendor/github.com/rjeczalik/notify/watcher_trigger.go @@ -23,6 +23,7 @@ package notify import ( + "fmt" "os" "path/filepath" "strings" @@ -56,6 +57,19 @@ type trigger interface { IsStop(n interface{}, err error) bool } +// trgWatched is a the base data structure representing watched file/directory. +// The platform specific full data structure (watched) must embed this type. +type trgWatched struct { + // p is a path to watched file/directory. + p string + // fi provides information about watched file/dir. + fi os.FileInfo + // eDir represents events watched directly. + eDir Event + // eNonDir represents events watched indirectly. + eNonDir Event +} + // encode Event to native representation. Implementation is to be provided by // platform specific implementation. var encode func(Event, bool) int64 @@ -117,6 +131,9 @@ func (t *trg) Close() (err error) { dbgprintf("trg: closing native watch failed: %q\n", e) err = nonil(err, e) } + if remaining := len(t.pthLkp); remaining != 0 { + err = nonil(err, fmt.Errorf("Not all watches were removed: len(t.pthLkp) == %v", len(t.pthLkp))) + } t.Unlock() return } @@ -175,7 +192,7 @@ func decode(o int64, w Event) (e Event) { func (t *trg) watch(p string, e Event, fi os.FileInfo) error { if err := t.singlewatch(p, e, dir, fi); err != nil { if err != errAlreadyWatched { - return nil + return err } } if fi.IsDir() { @@ -361,7 +378,7 @@ func (t *trg) singleunwatch(p string, direct mode) error { } if w.eNonDir|w.eDir != 0 { mod := dir - if w.eNonDir == 0 { + if w.eNonDir != 0 { mod = ndir } if err := t.singlewatch(p, w.eNonDir|w.eDir, mod, |