hpcloud / tail

Go package for reading from continously updated files (tail -f)
MIT License
2.7k stars 502 forks source link

Calling Tail.Cleanup can prevent future tailing #153

Open danielnelson opened 5 years ago

danielnelson commented 5 years ago

Calling Cleanup() on a Tail can decrement the watch counter below zero, which can prevent future attempts to tail the file.

Here is some code that can be used to show the issue:

func main() {

    // Setup and tail, being careful to avoid issue #93
    t, err := tail.TailFile(os.Args[1], tail.Config{Follow: true})
    if err != nil {
        fmt.Println(err)
    }
    go func() {
        for line := range t.Lines {
        }
    }()
    t.Stop()
    t.Cleanup()

    // At this point, the watch count for this is negative, the next time we
    // try to tail a watch will not be set.

    t, err = tail.TailFile(os.Args[1], tail.Config{Follow: true})
    if err != nil {
        fmt.Println(err)
    }
    go func() {
        for line := range t.Lines {
            fmt.Printf("%q\n", line.Text)
        }
    }()
    t.Wait()
}

To duplicate:

go run ./main.go test.log

# from another shell
echo 1 >> test.log
echo 2 >> test.log

Expected: the lines appended to test.log should be printed to screen. Actual: no output


Looking into the history of this function, it appears it was originally added to close all inotify watches before the program exists and it did not originally require access to the Tail objects.

Since now you need the Tail to call, it seems preferrable to call Stop() instead. The Cleanup function also does not ensure that the watch count goes to zero, it just does a single decrement, which won't be enough if there are multiple tails on a file.