diff --git a/daemon/logger/loggerutils/logfile.go b/daemon/logger/loggerutils/logfile.go index fe338e53e8..68782c3f19 100644 --- a/daemon/logger/loggerutils/logfile.go +++ b/daemon/logger/loggerutils/logfile.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "os" + "runtime" "strconv" "strings" "sync" @@ -641,9 +642,20 @@ func followLogs(f *os.File, logWatcher *logger.LogWatcher, notifyRotate chan int } func watchFile(name string) (filenotify.FileWatcher, error) { - fileWatcher, err := filenotify.New() - if err != nil { - return nil, err + var fileWatcher filenotify.FileWatcher + + if runtime.GOOS == "windows" { + // FileWatcher on Windows files is based on the syscall notifications which has an issue becuase of file caching. + // It is based on ReadDirectoryChangesW() which doesn't detect writes to the cache. It detects writes to disk only. + // Becuase of the OS lazy writing, we don't get notifications for file writes and thereby the watcher + // doesn't work. Hence for Windows we will use poll based notifier. + fileWatcher = filenotify.NewPollingWatcher() + } else { + var err error + fileWatcher, err = filenotify.New() + if err != nil { + return nil, err + } } logger := logrus.WithFields(logrus.Fields{ @@ -652,6 +664,7 @@ func watchFile(name string) (filenotify.FileWatcher, error) { }) if err := fileWatcher.Add(name); err != nil { + // we will retry using file poller. logger.WithError(err).Warnf("falling back to file poller") fileWatcher.Close() fileWatcher = filenotify.NewPollingWatcher() @@ -662,5 +675,6 @@ func watchFile(name string) (filenotify.FileWatcher, error) { return nil, err } } + return fileWatcher, nil }