From: Pieter Droogendijk Date: Sat, 7 Feb 2015 21:39:58 +0000 (+0100) Subject: Close inotify fd from watcher, not from poller X-Git-Tag: v1.7.2~232 X-Git-Url: https://go.fuhry.dev/?a=commitdiff_plain;h=e4f72b22e536e520bbe6225ee827c4b3b0c7a8fa;p=fsnotify.git Close inotify fd from watcher, not from poller --- diff --git a/inotify.go b/inotify.go index e02bf12..5aa185b 100644 --- a/inotify.go +++ b/inotify.go @@ -23,6 +23,7 @@ type Watcher struct { Events chan Event Errors chan error mu sync.Mutex // Map access + fd int poller *fdPoller watches map[string]*watch // Map of inotify watches (key: path) paths map[int]string // Map of watched paths (key: watch descriptor) @@ -40,9 +41,11 @@ func NewWatcher() (*Watcher, error) { // Create epoll poller, err := newFdPoller(fd) if err != nil { + syscall.Close(fd) return nil, err } w := &Watcher{ + fd: fd, poller: poller, watches: make(map[string]*watch), paths: make(map[int]string), @@ -103,7 +106,7 @@ func (w *Watcher) Add(name string) error { watchEntry.flags |= flags flags |= syscall.IN_MASK_ADD } - wd, errno := syscall.InotifyAddWatch(w.poller.fd, name, flags) + wd, errno := syscall.InotifyAddWatch(w.fd, name, flags) if wd == -1 { return errno } @@ -129,7 +132,7 @@ func (w *Watcher) Remove(name string) error { if !ok { return fmt.Errorf("can't remove non-existent inotify watch for: %s", name) } - success, errno := syscall.InotifyRmWatch(w.poller.fd, watch.wd) + success, errno := syscall.InotifyRmWatch(w.fd, watch.wd) if success == -1 { return errno } @@ -155,6 +158,7 @@ func (w *Watcher) readEvents() { defer close(w.doneresp) defer close(w.Errors) defer close(w.Events) + defer syscall.Close(w.fd) defer w.poller.close() for { @@ -177,7 +181,7 @@ func (w *Watcher) readEvents() { continue } - n, errno = syscall.Read(w.poller.fd, buf[:]) + n, errno = syscall.Read(w.fd, buf[:]) // If a signal interrupted execution, see if we've been asked to close, and try again. // http://man7.org/linux/man-pages/man7/signal.7.html : // "Before Linux 3.8, reads from an inotify(7) file descriptor were not restartable" diff --git a/inotify_poller.go b/inotify_poller.go index 8a95df6..2f9cb23 100644 --- a/inotify_poller.go +++ b/inotify_poller.go @@ -33,7 +33,6 @@ func newFdPoller(fd int) (*fdPoller, error) { // Create pipe; pipe[0] is the read end, pipe[1] the write end. errno = syscall.Pipe(poller.pipe[:]) if errno != nil { - syscall.Close(poller.fd) syscall.Close(poller.epfd) return nil, errno } @@ -45,7 +44,6 @@ func newFdPoller(fd int) (*fdPoller, error) { } errno = syscall.EpollCtl(poller.epfd, syscall.EPOLL_CTL_ADD, poller.fd, &event) if errno != nil { - syscall.Close(poller.fd) syscall.Close(poller.epfd) syscall.Close(poller.pipe[0]) syscall.Close(poller.pipe[1]) @@ -59,7 +57,6 @@ func newFdPoller(fd int) (*fdPoller, error) { } errno = syscall.EpollCtl(poller.epfd, syscall.EPOLL_CTL_ADD, poller.pipe[0], &event) if errno != nil { - syscall.Close(poller.fd) syscall.Close(poller.epfd) syscall.Close(poller.pipe[0]) syscall.Close(poller.pipe[1]) @@ -171,10 +168,9 @@ func (poller *fdPoller) clearWake() error { return nil } -// Close all file descriptors. +// Close all poller file descriptors, but not the one passed to it. func (poller *fdPoller) close() { syscall.Close(poller.pipe[1]) syscall.Close(poller.pipe[0]) - syscall.Close(poller.fd) syscall.Close(poller.epfd) } diff --git a/inotify_test.go b/inotify_test.go index 1c26a29..9d8e120 100644 --- a/inotify_test.go +++ b/inotify_test.go @@ -139,6 +139,7 @@ func TestInotifyCloseCreate(t *testing.T) { // Now we try to swap the file descriptor under its nose. w.Close() w, err = NewWatcher() + defer w.Close() if err != nil { t.Fatalf("Failed to create second watcher: %v", err) }