]> go.fuhry.dev Git - fsnotify.git/commitdiff
BSD - Fix issue reported by robfig
authorChris Howey <chris@howey.me>
Wed, 4 Apr 2012 03:24:59 +0000 (22:24 -0500)
committerChris Howey <chris@howey.me>
Wed, 4 Apr 2012 03:24:59 +0000 (22:24 -0500)
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.

fsnotify_bsd.go

index 0d8e0e59d2dc5355deeeffd08d74b6dd76f08f0b..872778b5e48d5b4dba83316286f23ca859ccac8d 100644 (file)
@@ -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