Fix: file-watcher bugs (#1897)

* Fix: file-watcher bugs

* Update watcher_linux.go

Co-authored-by: 杨铭哲 <yangmz@weipaitang.com>
Co-authored-by: Asim Aslam <asim@aslam.me>
This commit is contained in:
Z 2020-08-07 01:21:09 +08:00 committed by GitHub
parent 991cdba91d
commit dcf785677f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 36 deletions

View File

@ -10,6 +10,7 @@ import (
type file struct { type file struct {
path string path string
data []byte
opts source.Options opts source.Options
} }

View File

@ -39,26 +39,36 @@ func (w *watcher) Next() (*source.ChangeSet, error) {
default: default:
} }
// try get the event for {
select { // try get the event
case event, _ := <-w.fw.Events: select {
if event.Op == fsnotify.Rename { case event, _ := <-w.fw.Events:
// check existence of file, and add watch again if event.Op == fsnotify.Rename {
_, err := os.Stat(event.Name) // check existence of file, and add watch again
if err == nil || os.IsExist(err) { _, err := os.Stat(event.Name)
w.fw.Add(event.Name) if err == nil || os.IsExist(err) {
w.fw.Add(event.Name)
}
} }
}
c, err := w.f.Read() // ARCH: Darwin Kernel Version 18.7.0
if err != nil { // ioutil.WriteFile truncates it before writing, but the problem is that
// you will receive two events(fsnotify.Chmod and fsnotify.Write).
// We can solve this problem by ignoring fsnotify.Chmod event.
if event.Op&fsnotify.Write != fsnotify.Write {
continue
}
c, err := w.f.Read()
if err != nil {
return nil, err
}
return c, nil
case err := <-w.fw.Errors:
return nil, err return nil, err
case <-w.exit:
return nil, source.ErrWatcherStopped
} }
return c, nil
case err := <-w.fw.Errors:
return nil, err
case <-w.exit:
return nil, source.ErrWatcherStopped
} }
} }

View File

@ -4,6 +4,7 @@ package file
import ( import (
"os" "os"
"reflect"
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
"github.com/micro/go-micro/v3/config/source" "github.com/micro/go-micro/v3/config/source"
@ -39,30 +40,38 @@ func (w *watcher) Next() (*source.ChangeSet, error) {
default: default:
} }
// try get the event for {
select { // try get the event
case event, _ := <-w.fw.Events: select {
if event.Op == fsnotify.Rename { case event, _ := <-w.fw.Events:
// check existence of file, and add watch again if event.Op == fsnotify.Rename {
_, err := os.Stat(event.Name) // check existence of file, and add watch again
if err == nil || os.IsExist(err) { _, err := os.Stat(event.Name)
w.fw.Add(event.Name) if err == nil || os.IsExist(err) {
w.fw.Add(event.Name)
}
} }
}
c, err := w.f.Read() c, err := w.f.Read()
if err != nil { if err != nil {
return nil, err
}
// ARCH: Linux centos-7.shared 3.10.0-693.5.2.el7.x86_64
// Sometimes, ioutil.WriteFile triggers multiple fsnotify.Write events, which may be a bug.
// Detect if the file has changed
if reflect.DeepEqual(c.Data, w.f.data) {
continue
}
w.f.data = c.Data
return c, nil
case err := <-w.fw.Errors:
return nil, err return nil, err
case <-w.exit:
return nil, source.ErrWatcherStopped
} }
// add path again for the event bug of fsnotify
w.fw.Add(w.f.path)
return c, nil
case err := <-w.fw.Errors:
return nil, err
case <-w.exit:
return nil, source.ErrWatcherStopped
} }
} }