From 274567a526aef3f3a91f4332518ecd912ad8e2db Mon Sep 17 00:00:00 2001 From: miraclesu Date: Thu, 24 Dec 2015 16:47:46 +0800 Subject: [PATCH] fix data race --- tail.go | 12 +++++++++++- watch/inotify.go | 9 ++++----- watch/polling.go | 19 ++++++++++--------- watch/watch.go | 2 +- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/tail.go b/tail.go index 83d5bc1..1bae11c 100644 --- a/tail.go +++ b/tail.go @@ -10,6 +10,7 @@ import ( "log" "os" "strings" + "sync" "time" "github.com/hpcloud/tail/ratelimiter" @@ -82,6 +83,8 @@ type Tail struct { changes *watch.FileChanges tomb.Tomb // provides: Done, Kill, Dying + + lk sync.Mutex } var ( @@ -140,7 +143,9 @@ func (tail *Tail) Tell() (offset int64, err error) { } offset, err = tail.file.Seek(0, os.SEEK_CUR) if err == nil { + tail.lk.Lock() offset -= int64(tail.reader.Buffered()) + tail.lk.Unlock() } return } @@ -187,7 +192,9 @@ func (tail *Tail) reopen() error { } func (tail *Tail) readLine() (string, error) { + tail.lk.Lock() line, err := tail.reader.ReadString('\n') + tail.lk.Unlock() if err != nil { // Note ReadString "returns the data read before the error" in // case of an error, including EOF, so we return it as is. The @@ -315,7 +322,10 @@ func (tail *Tail) waitForChanges() error { if err != nil { return err } - tail.changes = tail.watcher.ChangeEvents(&tail.Tomb, pos) + tail.changes, err = tail.watcher.ChangeEvents(&tail.Tomb, pos) + if err != nil { + return err + } } select { diff --git a/watch/inotify.go b/watch/inotify.go index 8d11f10..58efc10 100644 --- a/watch/inotify.go +++ b/watch/inotify.go @@ -55,14 +55,13 @@ func (fw *InotifyFileWatcher) BlockUntilExists(t *tomb.Tomb) error { panic("unreachable") } -func (fw *InotifyFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) *FileChanges { - changes := NewFileChanges() - +func (fw *InotifyFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) (*FileChanges, error) { err := Watch(fw.Filename) if err != nil { - go changes.NotifyDeleted() + return nil, err } + changes := NewFileChanges() fw.Size = pos go func() { @@ -116,5 +115,5 @@ func (fw *InotifyFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) *FileChanges } }() - return changes + return changes, nil } diff --git a/watch/polling.go b/watch/polling.go index 5479272..33b8b4d 100644 --- a/watch/polling.go +++ b/watch/polling.go @@ -3,11 +3,12 @@ package watch import ( - "github.com/hpcloud/tail/util" - "gopkg.in/tomb.v1" "os" "runtime" "time" + + "github.com/hpcloud/tail/util" + "gopkg.in/tomb.v1" ) // PollingFileWatcher polls the file for changes. @@ -40,7 +41,12 @@ func (fw *PollingFileWatcher) BlockUntilExists(t *tomb.Tomb) error { panic("unreachable") } -func (fw *PollingFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) *FileChanges { +func (fw *PollingFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) (*FileChanges, error) { + origFi, err := os.Stat(fw.Filename) + if err != nil { + return nil, err + } + changes := NewFileChanges() var prevModTime time.Time @@ -48,11 +54,6 @@ func (fw *PollingFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) *FileChanges // the fatal (below) with tomb's Kill. fw.Size = pos - origFi, err := os.Stat(fw.Filename) - if err != nil { - changes.NotifyDeleted() - return changes - } go func() { defer changes.Close() @@ -110,7 +111,7 @@ func (fw *PollingFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) *FileChanges } }() - return changes + return changes, nil } func init() { diff --git a/watch/watch.go b/watch/watch.go index fbc08a5..05baea1 100644 --- a/watch/watch.go +++ b/watch/watch.go @@ -15,5 +15,5 @@ type FileWatcher interface { // or truncation event. // In order to properly report truncations, ChangeEvents requires // the caller to pass their current offset in the file. - ChangeEvents(*tomb.Tomb, int64) *FileChanges + ChangeEvents(*tomb.Tomb, int64) (*FileChanges, error) }