From: Chris Howey Date: Wed, 4 Apr 2012 03:24:59 +0000 (-0500) Subject: BSD - Fix issue reported by robfig X-Git-Tag: v1.7.2~437 X-Git-Url: https://go.fuhry.dev/?a=commitdiff_plain;h=cee331a3b3ed500e2f3311c2c4f84cb5933f87aa;p=fsnotify.git BSD - Fix issue reported by robfig EINTR can be returned by kevent in two cases: 1) fork() while parent/child is calling kevent() will result in the process calling kevent() to get EINTR while other process is registering the same kqueue at the kernel level. 2) A file event occurs before timeout expires, but is not yet on the queue to be returned by kevent(). In either case, we can ignore the error and continue as if timeout expired without any events. --- diff --git a/fsnotify_bsd.go b/fsnotify_bsd.go index 0d8e0e5..872778b 100644 --- a/fsnotify_bsd.go +++ b/fsnotify_bsd.go @@ -50,7 +50,9 @@ func (e *FileEvent) IsCreate() bool { return e.create } func (e *FileEvent) IsDelete() bool { return (e.mask & NOTE_DELETE) == NOTE_DELETE } // IsModify reports whether the FileEvent was triggerd by a file modification -func (e *FileEvent) IsModify() bool { return ((e.mask & NOTE_WRITE) == NOTE_WRITE || (e.mask & NOTE_ATTRIB) == NOTE_ATTRIB) } +func (e *FileEvent) IsModify() bool { + return ((e.mask&NOTE_WRITE) == NOTE_WRITE || (e.mask&NOTE_ATTRIB) == NOTE_ATTRIB) +} // IsRename reports whether the FileEvent was triggerd by a change name func (e *FileEvent) IsRename() bool { return (e.mask & NOTE_RENAME) == NOTE_RENAME } @@ -183,10 +185,6 @@ func (w *Watcher) readEvents() { *twait = syscall.NsecToTimespec(keventWaitTime) for { - if len(events) == 0 { - n, errno = syscall.Kevent(w.kq, nil, eventbuf[:], twait) - events = eventbuf[0:n] - } // See if there is a message on the "done" channel var done bool select { @@ -204,9 +202,19 @@ func (w *Watcher) readEvents() { close(w.Error) return } - if n < 0 { - w.Error <- os.NewSyscallError("kevent", errno) - continue + + // Get new events + if len(events) == 0 { + n, errno = syscall.Kevent(w.kq, nil, eventbuf[:], twait) + + // EINTR is okay, basically the syscall was interrupted before + // timeout expired. + if errno != nil && errno != syscall.EINTR { + w.Error <- os.NewSyscallError("kevent", errno) + continue + } else { + events = eventbuf[0:n] + } } // Timeout, no big deal