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{}) {