monitor: Fix a crash around the MONITOR command

This commit is contained in:
Daniel Oaks 2017-09-25 11:29:27 +10:00
parent 7ff33b88dd
commit e95c75f87d
3 changed files with 39 additions and 6 deletions

View File

@ -61,6 +61,7 @@ type Client struct {
isDestroyed bool isDestroyed bool
isQuitting bool isQuitting bool
monitoring map[string]bool monitoring map[string]bool
monitoringMutex sync.RWMutex
nick string nick string
nickCasefolded string nickCasefolded string
nickMaskCasefolded string nickMaskCasefolded string
@ -523,9 +524,11 @@ func (client *Client) destroy() {
} }
// alert monitors // alert monitors
client.server.monitoringMutex.RLock()
for _, mClient := range client.server.monitoring[client.nickCasefolded] { for _, mClient := range client.server.monitoring[client.nickCasefolded] {
mClient.Send(nil, client.server.name, RPL_MONOFFLINE, mClient.nick, client.nick) mClient.Send(nil, client.server.name, RPL_MONOFFLINE, mClient.nick, client.nick)
} }
client.server.monitoringMutex.RUnlock()
// remove my monitors // remove my monitors
client.clearMonitorList() client.clearMonitorList()

View File

@ -12,8 +12,13 @@ import (
// alertMonitors alerts everyone monitoring us that we're online. // alertMonitors alerts everyone monitoring us that we're online.
func (client *Client) alertMonitors() { func (client *Client) alertMonitors() {
// get monitors
client.server.monitoringMutex.RLock()
monitors := client.server.monitoring[client.nickCasefolded]
client.server.monitoringMutex.RUnlock()
// alert monitors // alert monitors
for _, mClient := range client.server.monitoring[client.nickCasefolded] { for _, mClient := range monitors {
// don't have to notify ourselves // don't have to notify ourselves
if mClient != client { if mClient != client {
mClient.SendFromClient("", client, nil, RPL_MONONLINE, mClient.nick, client.nickMaskString) mClient.SendFromClient("", client, nil, RPL_MONONLINE, mClient.nick, client.nickMaskString)
@ -23,6 +28,12 @@ func (client *Client) alertMonitors() {
// clearMonitorList clears our MONITOR list. // clearMonitorList clears our MONITOR list.
func (client *Client) clearMonitorList() { func (client *Client) clearMonitorList() {
// lockin' everything
client.monitoringMutex.Lock()
defer client.monitoringMutex.Unlock()
client.server.monitoringMutex.Lock()
defer client.server.monitoringMutex.Unlock()
for name := range client.monitoring { for name := range client.monitoring {
// just removes current client from the list // just removes current client from the list
orig := client.server.monitoring[name] orig := client.server.monitoring[name]
@ -82,6 +93,9 @@ func monitorRemoveHandler(server *Server, client *Client, msg ircmsg.IrcMessage)
continue continue
} }
client.monitoringMutex.Lock()
client.server.monitoringMutex.Lock()
if client.monitoring[casefoldedTarget] { if client.monitoring[casefoldedTarget] {
// just removes current client from the list // just removes current client from the list
orig := server.monitoring[casefoldedTarget] orig := server.monitoring[casefoldedTarget]
@ -97,6 +111,9 @@ func monitorRemoveHandler(server *Server, client *Client, msg ircmsg.IrcMessage)
delete(client.monitoring, casefoldedTarget) delete(client.monitoring, casefoldedTarget)
} }
client.monitoringMutex.Unlock()
client.server.monitoringMutex.Unlock()
// remove first element of targets list // remove first element of targets list
targets = targets[1:] targets = targets[1:]
} }
@ -135,6 +152,9 @@ func monitorAddHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bo
continue continue
} }
client.monitoringMutex.Lock()
client.server.monitoringMutex.Lock()
if !client.monitoring[casefoldedTarget] { if !client.monitoring[casefoldedTarget] {
client.monitoring[casefoldedTarget] = true client.monitoring[casefoldedTarget] = true
@ -142,6 +162,9 @@ func monitorAddHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bo
server.monitoring[casefoldedTarget] = append(orig, client) server.monitoring[casefoldedTarget] = append(orig, client)
} }
client.monitoringMutex.Unlock()
client.server.monitoringMutex.Unlock()
// add to online / offline lists // add to online / offline lists
target := server.clients.Get(casefoldedTarget) target := server.clients.Get(casefoldedTarget)
if target == nil { if target == nil {
@ -172,9 +195,11 @@ func monitorClearHandler(server *Server, client *Client, msg ircmsg.IrcMessage)
func monitorListHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool { func monitorListHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
var monitorList []string var monitorList []string
client.monitoringMutex.RLock()
for name := range client.monitoring { for name := range client.monitoring {
monitorList = append(monitorList, name) monitorList = append(monitorList, name)
} }
client.monitoringMutex.RUnlock()
for _, line := range argsToStrings(maxLastArgLength, monitorList, ",") { for _, line := range argsToStrings(maxLastArgLength, monitorList, ",") {
client.Send(nil, server.name, RPL_MONLIST, client.nick, line) client.Send(nil, server.name, RPL_MONLIST, client.nick, line)
@ -187,7 +212,11 @@ func monitorStatusHandler(server *Server, client *Client, msg ircmsg.IrcMessage)
var online []string var online []string
var offline []string var offline []string
for name := range client.monitoring { client.monitoringMutex.RLock()
monitoring := client.monitoring
client.monitoringMutex.RUnlock()
for name := range monitoring {
target := server.clients.Get(name) target := server.clients.Get(name)
if target == nil { if target == nil {
offline = append(offline, name) offline = append(offline, name)

View File

@ -95,6 +95,7 @@ type Server struct {
logger *logger.Manager logger *logger.Manager
MaxSendQBytes uint64 MaxSendQBytes uint64
monitoring map[string][]*Client monitoring map[string][]*Client
monitoringMutex sync.RWMutex
motdLines []string motdLines []string
name string name string
nameCasefolded string nameCasefolded string