From e11c1f75d9b6a922a1bd20a62a72b805fcf7dbcc Mon Sep 17 00:00:00 2001 From: Alex Velea Date: Wed, 12 Jul 2023 19:33:24 +0300 Subject: [PATCH 1/3] fix log.With() race condition - added small unittest to highlight the problem - only visible when running with -race option --- logger.go | 2 ++ logger_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/logger.go b/logger.go index f49d85d..cbf591f 100644 --- a/logger.go +++ b/logger.go @@ -285,7 +285,9 @@ func (l *Logger) SetCallerOffset(offset int) { // With returns a new logger with the given keyvals added. func (l *Logger) With(keyvals ...interface{}) *Logger { + l.mu.Lock() sl := *l + l.mu.Unlock() sl.b = bytes.Buffer{} sl.mu = &sync.RWMutex{} sl.helpers = &sync.Map{} diff --git a/logger_test.go b/logger_test.go index 67b831d..715fc5d 100644 --- a/logger_test.go +++ b/logger_test.go @@ -2,6 +2,7 @@ package log import ( "bytes" + "sync" "testing" "github.com/stretchr/testify/assert" @@ -151,3 +152,34 @@ func TestLogWithPrefix(t *testing.T) { }) } } + +func TestLogWithRaceCondition(t *testing.T) { + var buf bytes.Buffer + cases := []struct { + name string + }{ + { + name: "must be run with -race", + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + buf.Reset() + l := New(&buf) + + var done sync.WaitGroup + done.Add(2) + + go func() { + l.With("arg1", "val1", "arg2", "val2") + done.Done() + }() + + go func() { + l.Info("kinda long log message") + done.Done() + }() + done.Wait() + }) + } +} From 04d46ed72ae22a92179ebb6e142c3c6fd3a0a934 Mon Sep 17 00:00:00 2001 From: Alex Velea Date: Wed, 12 Jul 2023 21:11:28 +0300 Subject: [PATCH 2/3] rollback fix --- logger.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/logger.go b/logger.go index cbf591f..f49d85d 100644 --- a/logger.go +++ b/logger.go @@ -285,9 +285,7 @@ func (l *Logger) SetCallerOffset(offset int) { // With returns a new logger with the given keyvals added. func (l *Logger) With(keyvals ...interface{}) *Logger { - l.mu.Lock() sl := *l - l.mu.Unlock() sl.b = bytes.Buffer{} sl.mu = &sync.RWMutex{} sl.helpers = &sync.Map{} From e11ecdd1fd66c8de2c054f8c63dcff328e6dd6f0 Mon Sep 17 00:00:00 2001 From: Alex Velea Date: Thu, 13 Jul 2023 00:21:59 +0300 Subject: [PATCH 3/3] fix race condition --- logger.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/logger.go b/logger.go index f49d85d..cbf591f 100644 --- a/logger.go +++ b/logger.go @@ -285,7 +285,9 @@ func (l *Logger) SetCallerOffset(offset int) { // With returns a new logger with the given keyvals added. func (l *Logger) With(keyvals ...interface{}) *Logger { + l.mu.Lock() sl := *l + l.mu.Unlock() sl.b = bytes.Buffer{} sl.mu = &sync.RWMutex{} sl.helpers = &sync.Map{}