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:
commit
88298d7cf8
11
tail.go
11
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
|
||||
|
@ -155,7 +158,9 @@ func (tail *Tail) tailFileSync() {
|
|||
// deferred first open.
|
||||
err := tail.reopen()
|
||||
if err != nil {
|
||||
tail.Kill(err)
|
||||
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 {
|
||||
|
|
10
tail_test.go
10
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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue