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

Fix data race on kevent buffer. #98

Merged
merged 1 commit into from
Jun 17, 2014
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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