Skip to content

Commit a87f98a

Browse files
committed
Fix races in the log module by using syncmap
1 parent fac7a6f commit a87f98a

File tree

5 files changed

+455
-26
lines changed

5 files changed

+455
-26
lines changed

modules/log/log.go

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import (
1212
"runtime"
1313
"strings"
1414
"sync"
15+
16+
"golang.org/x/sync/syncmap"
1517
)
1618

1719
var (
@@ -42,10 +44,11 @@ func NewLogger(bufLen int64, mode, config string) {
4244
// DelLogger removes loggers that are for the given mode
4345
func DelLogger(mode string) error {
4446
for _, l := range loggers {
45-
if _, ok := l.outputs[mode]; ok {
47+
if _, ok := l.outputs.Load(mode); ok {
4648
return l.DelLogger(mode)
4749
}
4850
}
51+
4952
Trace("Log adapter %s not found, no need to delete", mode)
5053
return nil
5154
}
@@ -177,31 +180,28 @@ type Logger struct {
177180
lock sync.Mutex
178181
level int
179182
msg chan *logMsg
180-
outputs map[string]LoggerInterface
183+
outputs syncmap.Map
181184
quit chan bool
182185
}
183186

184187
// newLogger initializes and returns a new logger.
185188
func newLogger(buffer int64) *Logger {
186189
l := &Logger{
187-
msg: make(chan *logMsg, buffer),
188-
outputs: make(map[string]LoggerInterface),
189-
quit: make(chan bool),
190+
msg: make(chan *logMsg, buffer),
191+
quit: make(chan bool),
190192
}
191193
go l.StartLogger()
192194
return l
193195
}
194196

195197
// SetLogger sets new logger instance with given logger adapter and config.
196198
func (l *Logger) SetLogger(adapter string, config string) error {
197-
l.lock.Lock()
198-
defer l.lock.Unlock()
199199
if log, ok := adapters[adapter]; ok {
200200
lg := log()
201201
if err := lg.Init(config); err != nil {
202202
return err
203203
}
204-
l.outputs[adapter] = lg
204+
l.outputs.Store(adapter, lg)
205205
l.adapter = adapter
206206
} else {
207207
panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)")
@@ -211,11 +211,9 @@ func (l *Logger) SetLogger(adapter string, config string) error {
211211

212212
// DelLogger removes a logger adapter instance.
213213
func (l *Logger) DelLogger(adapter string) error {
214-
l.lock.Lock()
215-
defer l.lock.Unlock()
216-
if lg, ok := l.outputs[adapter]; ok {
217-
lg.Destroy()
218-
delete(l.outputs, adapter)
214+
if lg, ok := l.outputs.Load(adapter); ok {
215+
lg.(LoggerInterface).Destroy()
216+
l.outputs.Delete(adapter)
219217
} else {
220218
panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)")
221219
}
@@ -264,11 +262,12 @@ func (l *Logger) StartLogger() {
264262
for {
265263
select {
266264
case bm := <-l.msg:
267-
for _, l := range l.outputs {
268-
if err := l.WriteMsg(bm.msg, bm.skip, bm.level); err != nil {
265+
l.outputs.Range(func(k, v interface{}) bool {
266+
if err := v.(LoggerInterface).WriteMsg(bm.msg, bm.skip, bm.level); err != nil {
269267
fmt.Println("ERROR, unable to WriteMsg:", err)
270268
}
271-
}
269+
return true
270+
})
272271
case <-l.quit:
273272
return
274273
}
@@ -277,9 +276,10 @@ func (l *Logger) StartLogger() {
277276

278277
// Flush flushes all chan data.
279278
func (l *Logger) Flush() {
280-
for _, l := range l.outputs {
281-
l.Flush()
282-
}
279+
l.outputs.Range(func(k, v interface{}) bool {
280+
v.(LoggerInterface).Flush()
281+
return true
282+
})
283283
}
284284

285285
// Close closes logger, flush all chan data and destroy all adapter instances.
@@ -288,19 +288,21 @@ func (l *Logger) Close() {
288288
for {
289289
if len(l.msg) > 0 {
290290
bm := <-l.msg
291-
for _, l := range l.outputs {
292-
if err := l.WriteMsg(bm.msg, bm.skip, bm.level); err != nil {
291+
l.outputs.Range(func(k, v interface{}) bool {
292+
if err := v.(LoggerInterface).WriteMsg(bm.msg, bm.skip, bm.level); err != nil {
293293
fmt.Println("ERROR, unable to WriteMsg:", err)
294294
}
295-
}
295+
return true
296+
})
296297
} else {
297298
break
298299
}
299300
}
300-
for _, l := range l.outputs {
301-
l.Flush()
302-
l.Destroy()
303-
}
301+
l.outputs.Range(func(k, v interface{}) bool {
302+
v.(LoggerInterface).Flush()
303+
v.(LoggerInterface).Destroy()
304+
return true
305+
})
304306
}
305307

306308
// Trace records trace log

vendor/golang.org/x/sync/LICENSE

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/golang.org/x/sync/PATENTS

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)