diff --git a/irc/client.go b/irc/client.go index ca986273..1eb1fa11 100644 --- a/irc/client.go +++ b/irc/client.go @@ -483,9 +483,11 @@ func (client *Client) destroy() { client.clearMonitorList() // clean up channels + client.server.channelJoinPartMutex.Lock() for channel := range client.channels { channel.Quit(client, &friends) } + client.server.channelJoinPartMutex.Unlock() // clean up server client.server.clients.Remove(client) diff --git a/irc/server.go b/irc/server.go index 0921433b..aa9440bc 100644 --- a/irc/server.go +++ b/irc/server.go @@ -86,6 +86,7 @@ type Server struct { accounts map[string]*ClientAccount channelRegistrationEnabled bool channels ChannelNameMap + channelJoinPartMutex sync.Mutex // used when joining/parting channels to prevent stomping over each others' access and all checkIdent bool clients *ClientLookupSet commands chan Command @@ -802,6 +803,10 @@ func joinHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool { keys = strings.Split(msg.Params[1], ",") } + // get lock + server.channelJoinPartMutex.Lock() + defer server.channelJoinPartMutex.Unlock() + for i, name := range channels { casefoldedName, err := CasefoldChannel(name) if err != nil { @@ -838,6 +843,10 @@ func partHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool { reason = msg.Params[1] } + // get lock + server.channelJoinPartMutex.Lock() + defer server.channelJoinPartMutex.Unlock() + for _, chname := range channels { casefoldedChannelName, err := CasefoldChannel(chname) channel := server.channels.Get(casefoldedChannelName)