Added eventsMutex and wrap all events calls with it.

Due to some "golangish" code this library have possibility to
run into data race when application is working with callbacks.
This commit adds eventsMutex (which is a sync.Mutex), removed
all "golangish" ifs-map reads, and wrap events map read with
sync.Mutex to avoid data races.
This commit is contained in:
Stanislav N. aka pztrn 2017-10-03 02:03:43 +05:00
parent 1b0acb5f2f
commit e39cceace6
2 changed files with 30 additions and 7 deletions

View File

@ -13,13 +13,17 @@ import (
func (irc *Connection) AddCallback(eventcode string, callback func(*Event)) int {
eventcode = strings.ToUpper(eventcode)
id := 0
if _, ok := irc.events[eventcode]; !ok {
irc.eventsMutex.Lock()
_, ok := irc.events[eventcode]
if !ok {
irc.events[eventcode] = make(map[int]func(*Event))
id = 0
} else {
id = len(irc.events[eventcode])
}
irc.events[eventcode][id] = callback
irc.eventsMutex.Unlock()
return id
}
@ -28,15 +32,20 @@ func (irc *Connection) AddCallback(eventcode string, callback func(*Event)) int
func (irc *Connection) RemoveCallback(eventcode string, i int) bool {
eventcode = strings.ToUpper(eventcode)
if event, ok := irc.events[eventcode]; ok {
irc.eventsMutex.Lock()
event, ok := irc.events[eventcode]
if ok {
if _, ok := event[i]; ok {
delete(irc.events[eventcode], i)
irc.eventsMutex.Unlock()
return true
}
irc.Log.Printf("Event found, but no callback found at id %d\n", i)
irc.eventsMutex.Unlock()
return false
}
irc.eventsMutex.Unlock()
irc.Log.Println("Event not found")
return false
}
@ -46,10 +55,14 @@ func (irc *Connection) RemoveCallback(eventcode string, i int) bool {
func (irc *Connection) ClearCallback(eventcode string) bool {
eventcode = strings.ToUpper(eventcode)
if _, ok := irc.events[eventcode]; ok {
irc.eventsMutex.Lock()
_, ok := irc.events[eventcode]
if ok {
irc.events[eventcode] = make(map[int]func(*Event))
irc.eventsMutex.Unlock()
return true
}
irc.eventsMutex.Unlock()
irc.Log.Println("Event not found")
return false
@ -59,7 +72,10 @@ func (irc *Connection) ClearCallback(eventcode string) bool {
func (irc *Connection) ReplaceCallback(eventcode string, i int, callback func(*Event)) {
eventcode = strings.ToUpper(eventcode)
if event, ok := irc.events[eventcode]; ok {
irc.eventsMutex.Lock()
event, ok := irc.events[eventcode]
irc.eventsMutex.Unlock()
if ok {
if _, ok := event[i]; ok {
event[i] = callback
return
@ -109,7 +125,10 @@ func (irc *Connection) RunCallbacks(event *Event) {
event.Arguments[len(event.Arguments)-1] = msg
}
if callbacks, ok := irc.events[event.Code]; ok {
irc.eventsMutex.Lock()
callbacks, ok := irc.events[event.Code]
irc.eventsMutex.Unlock()
if ok {
if irc.VerboseCallbackHandler {
irc.Log.Printf("%v (%v) >> %#v\n", event.Code, len(callbacks), event)
}
@ -121,12 +140,15 @@ func (irc *Connection) RunCallbacks(event *Event) {
irc.Log.Printf("%v (0) >> %#v\n", event.Code, event)
}
if callbacks, ok := irc.events["*"]; ok {
irc.eventsMutex.Lock()
allcallbacks, ok := irc.events["*"]
irc.eventsMutex.Unlock()
if ok {
if irc.VerboseCallbackHandler {
irc.Log.Printf("%v (0) >> %#v\n", event.Code, event)
}
for _, callback := range callbacks {
for _, callback := range allcallbacks {
callback(event)
}
}

View File

@ -39,6 +39,7 @@ type Connection struct {
user string
registered bool
events map[string]map[int]func(*Event)
eventsMutex sync.Mutex
QuitMessage string
lastMessage time.Time