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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
}
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 @@
}
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 @@
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 @@
// 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)
}