From c412566267ae05305c21226d35d05216b1da05bd Mon Sep 17 00:00:00 2001 From: mstmdev Date: Fri, 7 Jan 2022 00:42:39 +0800 Subject: [PATCH] Fix the problem of data race for fileLogger --- VERSION | 2 +- file_logger.go | 24 ++++++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/VERSION b/VERSION index 04eddb2..e1d848b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v0.0.7 \ No newline at end of file +v0.0.8 \ No newline at end of file diff --git a/file_logger.go b/file_logger.go index 88065d3..823a7fd 100644 --- a/file_logger.go +++ b/file_logger.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "path/filepath" + "sync" "time" ) @@ -20,6 +21,7 @@ type fileLogger struct { close chan bool // the log is closed, and wait to write all the logs autoFlush bool flushInterval time.Duration + mu sync.Mutex // avoid data race for writer } type logMsg struct { @@ -47,6 +49,7 @@ func NewFileLoggerWithAutoFlush(level Level, logDir string, filePrefix string, a filePrefix: filePrefix, autoFlush: autoFlush, flushInterval: flushInterval, + mu: sync.Mutex{}, } // init baseLogger logger.baseLogger.init(logger, level) @@ -116,6 +119,8 @@ func (l *fileLogger) start() { func (l *fileLogger) write() { msg := <-l.in + l.mu.Lock() + defer l.mu.Unlock() // if received a closed message, flush logs to file, and notify close finished. if msg.closed { if l.initialized && l.writer != nil { @@ -151,10 +156,13 @@ func (l *fileLogger) startAutoFlush() { for { <-time.After(wait) if l.closed || l.writer == nil { - l.innerLog("autoFlush stopped") + l.innerLog("auto flush stopped") return } - if l.writer.Buffered() > 0 { + l.mu.Lock() + buffered := l.writer.Buffered() + l.mu.Unlock() + if buffered > 0 { l.in <- flushLogMsg wait = l.flushInterval nop = 0 @@ -169,13 +177,21 @@ func (l *fileLogger) startAutoFlush() { }() } +// Write see io.Writer func (l *fileLogger) Write(p []byte) (n int, err error) { + // copy data to avoid data race from caller + pLen := len(p) + if pLen == 0 { + return 0, nil + } + cp := make([]byte, pLen) + copy(cp, p) if l.initialized && !l.closed { l.in <- logMsg{ - log: p, + log: cp, closed: false, } - return len(p), nil + return pLen, nil } else { return 0, errors.New("file logger is uninitialized or closed") }