Skip to content

Commit

Permalink
Fix races in the log module by using syncmap
Browse files Browse the repository at this point in the history
  • Loading branch information
typeless committed Apr 1, 2017
1 parent fac7a6f commit a87f98a
Show file tree
Hide file tree
Showing 5 changed files with 455 additions and 26 deletions.
54 changes: 28 additions & 26 deletions modules/log/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"runtime"
"strings"
"sync"

"golang.org/x/sync/syncmap"
)

var (
Expand Down Expand Up @@ -42,10 +44,11 @@ func NewLogger(bufLen int64, mode, config string) {
// DelLogger removes loggers that are for the given mode
func DelLogger(mode string) error {
for _, l := range loggers {
if _, ok := l.outputs[mode]; ok {
if _, ok := l.outputs.Load(mode); ok {
return l.DelLogger(mode)
}
}

Trace("Log adapter %s not found, no need to delete", mode)
return nil
}
Expand Down Expand Up @@ -177,31 +180,28 @@ type Logger struct {
lock sync.Mutex
level int
msg chan *logMsg
outputs map[string]LoggerInterface
outputs syncmap.Map
quit chan bool
}

// newLogger initializes and returns a new logger.
func newLogger(buffer int64) *Logger {
l := &Logger{
msg: make(chan *logMsg, buffer),
outputs: make(map[string]LoggerInterface),
quit: make(chan bool),
msg: make(chan *logMsg, buffer),
quit: make(chan bool),
}
go l.StartLogger()
return l
}

// SetLogger sets new logger instance with given logger adapter and config.
func (l *Logger) SetLogger(adapter string, config string) error {
l.lock.Lock()
defer l.lock.Unlock()
if log, ok := adapters[adapter]; ok {
lg := log()
if err := lg.Init(config); err != nil {
return err
}
l.outputs[adapter] = lg
l.outputs.Store(adapter, lg)
l.adapter = adapter
} else {
panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)")
Expand All @@ -211,11 +211,9 @@ func (l *Logger) SetLogger(adapter string, config string) error {

// DelLogger removes a logger adapter instance.
func (l *Logger) DelLogger(adapter string) error {
l.lock.Lock()
defer l.lock.Unlock()
if lg, ok := l.outputs[adapter]; ok {
lg.Destroy()
delete(l.outputs, adapter)
if lg, ok := l.outputs.Load(adapter); ok {
lg.(LoggerInterface).Destroy()
l.outputs.Delete(adapter)
} else {
panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)")
}
Expand Down Expand Up @@ -264,11 +262,12 @@ func (l *Logger) StartLogger() {
for {
select {
case bm := <-l.msg:
for _, l := range l.outputs {
if err := l.WriteMsg(bm.msg, bm.skip, bm.level); err != nil {
l.outputs.Range(func(k, v interface{}) bool {
if err := v.(LoggerInterface).WriteMsg(bm.msg, bm.skip, bm.level); err != nil {
fmt.Println("ERROR, unable to WriteMsg:", err)
}
}
return true
})
case <-l.quit:
return
}
Expand All @@ -277,9 +276,10 @@ func (l *Logger) StartLogger() {

// Flush flushes all chan data.
func (l *Logger) Flush() {
for _, l := range l.outputs {
l.Flush()
}
l.outputs.Range(func(k, v interface{}) bool {
v.(LoggerInterface).Flush()
return true
})
}

// Close closes logger, flush all chan data and destroy all adapter instances.
Expand All @@ -288,19 +288,21 @@ func (l *Logger) Close() {
for {
if len(l.msg) > 0 {
bm := <-l.msg
for _, l := range l.outputs {
if err := l.WriteMsg(bm.msg, bm.skip, bm.level); err != nil {
l.outputs.Range(func(k, v interface{}) bool {
if err := v.(LoggerInterface).WriteMsg(bm.msg, bm.skip, bm.level); err != nil {
fmt.Println("ERROR, unable to WriteMsg:", err)
}
}
return true
})
} else {
break
}
}
for _, l := range l.outputs {
l.Flush()
l.Destroy()
}
l.outputs.Range(func(k, v interface{}) bool {
v.(LoggerInterface).Flush()
v.(LoggerInterface).Destroy()
return true
})
}

// Trace records trace log
Expand Down
27 changes: 27 additions & 0 deletions vendor/golang.org/x/sync/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions vendor/golang.org/x/sync/PATENTS

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit a87f98a

Please sign in to comment.