more fine-grained locking around user map (fixes deadlock if callee uses Users() in response to processEvent)

This commit is contained in:
mappu 2017-02-05 19:06:17 +13:00
parent 7f898dff32
commit 3cc31323ad
1 changed files with 7 additions and 10 deletions

View File

@ -67,10 +67,11 @@ func (this *HubConnection) UserCount() int {
func (this *HubConnection) userJoined_NameOnly(nick string) {
if !this.UserExists(nick) {
this.userLock.Lock()
defer this.userLock.Unlock()
this.userLock.Lock()
this.users[nick] = *NewUserInfo(nick)
this.userLock.Unlock() // Don't lock over a processEvent boundary
this.processEvent(HubEvent{EventType: EVENT_USER_JOINED, Nick: nick})
}
}
@ -78,11 +79,9 @@ func (this *HubConnection) userJoined_NameOnly(nick string) {
func (this *HubConnection) userJoined_Full(uinf *UserInfo) {
// n.b. also called when we get a replacement MyINFO for someone
this.userLock.Lock()
defer this.userLock.Unlock()
_, userExisted := this.users[uinf.Nick] // don't use UserExists as it would deadlock the mutex
this.users[uinf.Nick] = *uinf
this.userLock.Unlock() // Don't lock over a processEvent boundary
if !userExisted {
this.processEvent(HubEvent{EventType: EVENT_USER_JOINED, Nick: uinf.Nick})
@ -177,12 +176,10 @@ func (this *HubConnection) processProtocolMessage(message string) {
}
case "$Quit":
func() {
this.userLock.Lock()
defer this.userLock.Unlock()
this.userLock.Lock()
delete(this.users, commandParts[1])
this.userLock.Unlock() // Don't lock over a processEvent boundary
delete(this.users, commandParts[1])
}()
this.processEvent(HubEvent{EventType: EVENT_USER_PART, Nick: commandParts[1]})
case "$MyINFO":