From 3cb58e571f18a6e4cdc2c299560ca2abd5958ea7 Mon Sep 17 00:00:00 2001 From: Asal Mirzaieva <asal.mirzaieva@holoplot.com> Date: Mon, 18 May 2020 10:39:45 +0200 Subject: [PATCH] backend, logger: lock before reassigning `defaultBackend` If not locked, this results in race: 1. SetBackend(), backend.go:26 - reassigning the global variable (write) ``` func SetBackend(backends ...Backend) LeveledBackend { var backend Backend // ... // DARA RACE START defaultBackend = AddModuleLevel(backend) // DATA RACE END return defaultBackend } ``` 2. IsEnabledFor(), logger.go:141 - accessing a default variable (read) ``` func (l *Logger) IsEnabledFor(level Level) bool { return defaultBackend.IsEnabledFor(level, l.Module) // DATA RACE HERE } ``` --- backend.go | 2 ++ level.go | 19 +++++++++++-------- logger.go | 5 ++++- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/backend.go b/backend.go index 74d9201..8df5d67 100644 --- a/backend.go +++ b/backend.go @@ -23,7 +23,9 @@ func SetBackend(backends ...Backend) LeveledBackend { backend = MultiLogger(backends...) } + lock.Lock() defaultBackend = AddModuleLevel(backend) + lock.Unlock() return defaultBackend } diff --git a/level.go b/level.go index 98dd191..b952f75 100644 --- a/level.go +++ b/level.go @@ -26,14 +26,17 @@ const ( DEBUG ) -var levelNames = []string{ - "CRITICAL", - "ERROR", - "WARNING", - "NOTICE", - "INFO", - "DEBUG", -} +var ( + lock sync.Mutex + levelNames = []string{ + "CRITICAL", + "ERROR", + "WARNING", + "NOTICE", + "INFO", + "DEBUG", + } +) // String returns the string representation of a logging level. func (p Level) String() string { diff --git a/logger.go b/logger.go index 535ed9b..ce563c3 100644 --- a/logger.go +++ b/logger.go @@ -137,7 +137,10 @@ func Reset() { // IsEnabledFor returns true if the logger is enabled for the given level. func (l *Logger) IsEnabledFor(level Level) bool { - return defaultBackend.IsEnabledFor(level, l.Module) + lock.Lock() + enabled := defaultBackend.IsEnabledFor(level, l.Module) + defer lock.Unlock() + return enabled } func (l *Logger) log(lvl Level, format *string, args ...interface{}) {