Skip to content
This repository has been archived by the owner on Jun 8, 2022. It is now read-only.

Commit

Permalink
Merge pull request #98 from tilaks/master
Browse files Browse the repository at this point in the history
Fix data race on kevent buffer.

Not sure why a mutex doesn't work, but this fix will work.
  • Loading branch information
howeyc committed Jun 17, 2014
2 parents 441bbc8 + 35a7e13 commit 13cd45d
Showing 1 changed file with 9 additions and 13 deletions.
22 changes: 9 additions & 13 deletions fsnotify_bsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ type Watcher struct {
Event chan *FileEvent // Events are returned on this channel
done chan bool // Channel for sending a "quit message" to the reader goroutine
isClosed bool // Set to true when Close() is first called
kbuf [1]syscall.Kevent_t // An event buffer for Add/Remove watch
bufmut sync.Mutex // Protects access to kbuf.
}

// NewWatcher creates and returns a new kevent instance using kqueue(2)
Expand Down Expand Up @@ -207,15 +205,13 @@ func (w *Watcher) addWatch(path string, flags uint32) error {
w.enFlags[path] = flags
w.enmut.Unlock()

w.bufmut.Lock()
watchEntry := &w.kbuf[0]
var kbuf [1]syscall.Kevent_t
watchEntry := &kbuf[0]
watchEntry.Fflags = flags
syscall.SetKevent(watchEntry, watchfd, syscall.EVFILT_VNODE, syscall.EV_ADD|syscall.EV_CLEAR)
entryFlags := watchEntry.Flags
w.bufmut.Unlock()

wd, errno := syscall.Kevent(w.kq, w.kbuf[:], nil, nil)
if wd == -1 {
success, errno := syscall.Kevent(w.kq, kbuf[:], nil, nil)
if success == -1 {
return errno
} else if (entryFlags & syscall.EV_ERROR) == syscall.EV_ERROR {
return errors.New("kevent add error")
Expand Down Expand Up @@ -246,14 +242,14 @@ func (w *Watcher) removeWatch(path string) error {
if !ok {
return errors.New(fmt.Sprintf("can't remove non-existent kevent watch for: %s", path))
}
w.bufmut.Lock()
watchEntry := &w.kbuf[0]
var kbuf [1]syscall.Kevent_t
watchEntry := &kbuf[0]
syscall.SetKevent(watchEntry, watchfd, syscall.EVFILT_VNODE, syscall.EV_DELETE)
success, errno := syscall.Kevent(w.kq, w.kbuf[:], nil, nil)
w.bufmut.Unlock()
entryFlags := watchEntry.Flags
success, errno := syscall.Kevent(w.kq, kbuf[:], nil, nil)
if success == -1 {
return os.NewSyscallError("kevent_rm_watch", errno)
} else if (watchEntry.Flags & syscall.EV_ERROR) == syscall.EV_ERROR {
} else if (entryFlags & syscall.EV_ERROR) == syscall.EV_ERROR {
return errors.New("kevent rm error")
}
syscall.Close(watchfd)
Expand Down

0 comments on commit 13cd45d

Please sign in to comment.