diff --git a/tail.go b/tail.go index fa1d5f0..0a10f5b 100644 --- a/tail.go +++ b/tail.go @@ -130,7 +130,10 @@ func (tail *Tail) reopen() error { if err != nil { if os.IsNotExist(err) { log.Printf("Waiting for %s to appear...", tail.Filename) - if err := tail.watcher.BlockUntilExists(tail.Tomb); err != nil { + if err := tail.watcher.BlockUntilExists(&tail.Tomb); err != nil { + if err == tomb.ErrDying { + return err + } return fmt.Errorf("Failed to detect creation of %s: %s", tail.Filename, err) } continue @@ -154,6 +157,9 @@ func (tail *Tail) tailFileSync() { if !tail.MustExist { // deferred first open. err := tail.reopen() + if err == tomb.ErrDying { + return + } if err != nil { tail.Kill(err) return @@ -236,7 +242,7 @@ func (tail *Tail) waitForChanges() error { if err != nil { return err } - tail.changes = tail.watcher.ChangeEvents(tail.Tomb, st) + tail.changes = tail.watcher.ChangeEvents(&tail.Tomb, st) } select { diff --git a/tail_test.go b/tail_test.go index c9ec769..9440f95 100644 --- a/tail_test.go +++ b/tail_test.go @@ -40,6 +40,16 @@ func TestMustExist(t *testing.T) { tail.Stop() } +func TestStop(t *testing.T) { + tail, err := TailFile("_no_such_file", Config{Follow: true, MustExist: false}) + if err != nil { + t.Error("MustExist:false is violated") + } + if tail.Stop() != nil { + t.Error("Should be stoped successfully") + } +} + func TestMaxLineSize(_t *testing.T) { t := NewTailTest("maxlinesize", _t) t.CreateFile("test.txt", "hello\nworld\nfin\nhe") diff --git a/watch/inotify.go b/watch/inotify.go index 7cab0fd..895bc38 100644 --- a/watch/inotify.go +++ b/watch/inotify.go @@ -4,9 +4,9 @@ package watch import ( "github.com/howeyc/fsnotify" + "launchpad.net/tomb" "os" "path/filepath" - "launchpad.net/tomb" ) // InotifyFileWatcher uses inotify to monitor file changes. @@ -20,7 +20,7 @@ func NewInotifyFileWatcher(filename string) *InotifyFileWatcher { return fw } -func (fw *InotifyFileWatcher) BlockUntilExists(t tomb.Tomb) error { +func (fw *InotifyFileWatcher) BlockUntilExists(t *tomb.Tomb) error { w, err := fsnotify.NewWatcher() if err != nil { return err @@ -56,9 +56,9 @@ func (fw *InotifyFileWatcher) BlockUntilExists(t tomb.Tomb) error { panic("unreachable") } -func (fw *InotifyFileWatcher) ChangeEvents(t tomb.Tomb, fi os.FileInfo) *FileChanges { +func (fw *InotifyFileWatcher) ChangeEvents(t *tomb.Tomb, fi os.FileInfo) *FileChanges { changes := NewFileChanges() - + w, err := fsnotify.NewWatcher() if err != nil { panic(err) @@ -104,7 +104,7 @@ func (fw *InotifyFileWatcher) ChangeEvents(t tomb.Tomb, fi os.FileInfo) *FileCha if prevSize > 0 && prevSize > fw.Size { changes.NotifyTruncated() - }else{ + } else { changes.NotifyModified() } prevSize = fw.Size diff --git a/watch/polling.go b/watch/polling.go index a5d8fb0..bd048ae 100644 --- a/watch/polling.go +++ b/watch/polling.go @@ -21,7 +21,7 @@ func NewPollingFileWatcher(filename string) *PollingFileWatcher { var POLL_DURATION time.Duration -func (fw *PollingFileWatcher) BlockUntilExists(t tomb.Tomb) error { +func (fw *PollingFileWatcher) BlockUntilExists(t *tomb.Tomb) error { for { if _, err := os.Stat(fw.Filename); err == nil { return nil @@ -38,7 +38,7 @@ func (fw *PollingFileWatcher) BlockUntilExists(t tomb.Tomb) error { panic("unreachable") } -func (fw *PollingFileWatcher) ChangeEvents(t tomb.Tomb, origFi os.FileInfo) *FileChanges { +func (fw *PollingFileWatcher) ChangeEvents(t *tomb.Tomb, origFi os.FileInfo) *FileChanges { changes := NewFileChanges() var prevModTime time.Time @@ -49,7 +49,7 @@ func (fw *PollingFileWatcher) ChangeEvents(t tomb.Tomb, origFi os.FileInfo) *Fil go func() { defer changes.Close() - + prevSize := fw.Size for { select { diff --git a/watch/watch.go b/watch/watch.go index afff103..4967131 100644 --- a/watch/watch.go +++ b/watch/watch.go @@ -3,19 +3,18 @@ package watch import ( - "os" "launchpad.net/tomb" + "os" ) // FileWatcher monitors file-level events. type FileWatcher interface { // BlockUntilExists blocks until the file comes into existence. - BlockUntilExists(tomb.Tomb) error + BlockUntilExists(*tomb.Tomb) error // ChangeEvents reports on changes to a file, be it modification, // deletion, renames or truncations. Returned FileChanges group of // channels will be closed, thus become unusable, after a deletion // or truncation event. - ChangeEvents(tomb.Tomb, os.FileInfo) *FileChanges + ChangeEvents(*tomb.Tomb, os.FileInfo) *FileChanges } -