Skip to content

Commit

Permalink
watcher: ignore CHMOD, limit WaitForReplacement, longer sleep
Browse files Browse the repository at this point in the history
fix "done" chan, only used by tests:
the "break" just broke out of the select block, no the for loop
could use a label, simplest fix is to just return

simpler handling of CHMOD: just ignore it (if not also a rename or remove)

limit WaitForReplacement to about 2 seconds
(instead of waiting forever for file to re-appear)

WaitForReplacement sleeps first before re-checking, for 100ms (longer)
(makes travis-ci tests less flakey)
  • Loading branch information
ploxiln committed Nov 24, 2018
1 parent 260e055 commit b42b27e
Showing 1 changed file with 11 additions and 16 deletions.
27 changes: 11 additions & 16 deletions watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,18 @@ import (
"github.com/fsnotify/fsnotify"
)

func WaitForReplacement(filename string, op fsnotify.Op,
watcher *fsnotify.Watcher) {
const sleep_interval = 50 * time.Millisecond
func WaitForReplacement(filename string, watcher *fsnotify.Watcher) {
for i := 0; i < 20; i++ {
time.Sleep(100 * time.Millisecond)

// Avoid a race when fsnofity.Remove is preceded by fsnotify.Chmod.
if op&fsnotify.Chmod != 0 {
time.Sleep(sleep_interval)
}
for {
if _, err := os.Stat(filename); err == nil {
if err := watcher.Add(filename); err == nil {
log.Printf("watching resumed for %s", filename)
return
}
}
time.Sleep(sleep_interval)
}
log.Printf("failed to resume watching for %s", filename)
}

func WatchForUpdates(filename string, done <-chan bool, action func()) {
Expand All @@ -37,22 +32,22 @@ func WatchForUpdates(filename string, done <-chan bool, action func()) {
log.Fatal("failed to create watcher for ", filename, ": ", err)
}
go func() {
defer watcher.Close()
for {
select {
case _ = <-done:
log.Printf("Shutting down watcher for: %s", filename)
break
watcher.Close()
return
case event := <-watcher.Events:
// On Arch Linux, it appears Chmod events precede Remove events,
// which causes a race between action() and the coming Remove event.
// If the Remove wins, the action() (which calls
// UserMap.LoadAuthenticatedEmailsFile()) crashes when the file
// can't be opened.
if event.Op&(fsnotify.Remove|fsnotify.Rename|fsnotify.Chmod) != 0 {
if event.Op == fsnotify.Chmod {
continue
}
if event.Op&(fsnotify.Remove|fsnotify.Rename) != 0 {
log.Printf("watching interrupted on event: %s", event)
watcher.Remove(filename)
WaitForReplacement(filename, event.Op, watcher)
WaitForReplacement(filename, watcher)
}
log.Printf("reloading after event: %s", event)
action()
Expand Down

0 comments on commit b42b27e

Please sign in to comment.