diff --git a/lumberjack.go b/lumberjack.go index ca19da4..fb86ca5 100644 --- a/lumberjack.go +++ b/lumberjack.go @@ -32,6 +32,7 @@ import ( "sort" "strings" "sync" + "sync/atomic" "time" ) @@ -111,8 +112,8 @@ type Logger struct { file *os.File mu sync.Mutex - millCh chan bool - startMill sync.Once + millQueue int32 + millMu sync.Mutex } var ( @@ -302,6 +303,14 @@ func (l *Logger) filename() string { // files are removed, keeping at most l.MaxBackups files, as long as // none of them are older than MaxAge. func (l *Logger) millRunOnce() error { + + // ensure only one mill worker is working at once + l.millMu.Lock() + defer l.millMu.Unlock() + + // decrement mill queue to 0 to allow another goroutine to queue up + atomic.StoreInt32(&l.millQueue, 0) + if l.MaxBackups == 0 && l.MaxAge == 0 && !l.Compress { return nil } @@ -373,25 +382,11 @@ func (l *Logger) millRunOnce() error { return err } -// millRun runs in a goroutine to manage post-rotation compression and removal -// of old log files. -func (l *Logger) millRun() { - for _ = range l.millCh { - // what am I going to do, log this? - _ = l.millRunOnce() - } -} - // mill performs post-rotation compression and removal of stale log files, -// starting the mill goroutine if necessary. +// starting a mill goroutine if necessary. func (l *Logger) mill() { - l.startMill.Do(func() { - l.millCh = make(chan bool, 1) - go l.millRun() - }) - select { - case l.millCh <- true: - default: + if atomic.CompareAndSwapInt32(&l.millQueue, 0, 1) { + go l.millRunOnce() } }