diff --git a/watcher.go b/watcher.go index 48a57a229..a32e72e2a 100644 --- a/watcher.go +++ b/watcher.go @@ -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()) { @@ -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()