Merge pull request #18 from miraclesu/fix_stop_hang

Fix a hang in `Stop` when tailing a non-existent file

Reproducible on linux, but not on mac.
This commit is contained in:
Sridhar Ratnakumar 2013-09-23 18:19:18 -07:00
commit 88298d7cf8
5 changed files with 29 additions and 15 deletions

View File

@ -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
@ -155,7 +158,9 @@ func (tail *Tail) tailFileSync() {
// deferred first open.
err := tail.reopen()
if err != nil {
if err != tomb.ErrDying {
tail.Kill(err)
}
return
}
}
@ -236,7 +241,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 {

View File

@ -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")

View File

@ -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,7 +56,7 @@ 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()
@ -108,7 +108,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

View File

@ -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

View File

@ -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
}