Browse Source

fix #2113

Persisting always-on clients was panicking if client X believed it was
a member of channel Y, but channel Y didn't have a record of client X.
tags/v2.13.0-rc1
Shivaram Lingamneni 3 months ago
parent
commit
4aa1aa371d
2 changed files with 10 additions and 3 deletions
  1. 5
    2
      irc/channel.go
  2. 5
    1
      irc/client.go

+ 5
- 2
irc/channel.go View File

@@ -545,11 +545,14 @@ func (channel *Channel) ClientStatus(client *Client) (present bool, joinTimeSecs
545 545
 
546 546
 // helper for persisting channel-user modes for always-on clients;
547 547
 // return the channel name and all channel-user modes for a client
548
-func (channel *Channel) alwaysOnStatus(client *Client) (chname string, status alwaysOnChannelStatus) {
548
+func (channel *Channel) alwaysOnStatus(client *Client) (ok bool, chname string, status alwaysOnChannelStatus) {
549 549
 	channel.stateMutex.RLock()
550 550
 	defer channel.stateMutex.RUnlock()
551 551
 	chname = channel.name
552
-	data := channel.members[client]
552
+	data, ok := channel.members[client]
553
+	if !ok {
554
+		return
555
+	}
553 556
 	status.Modes = data.modes.String()
554 557
 	status.JoinTime = data.joinTime
555 558
 	return

+ 5
- 1
irc/client.go View File

@@ -1803,7 +1803,11 @@ func (client *Client) performWrite(additionalDirtyBits uint) {
1803 1803
 		channels := client.Channels()
1804 1804
 		channelToModes := make(map[string]alwaysOnChannelStatus, len(channels))
1805 1805
 		for _, channel := range channels {
1806
-			chname, status := channel.alwaysOnStatus(client)
1806
+			ok, chname, status := channel.alwaysOnStatus(client)
1807
+			if !ok {
1808
+				client.server.logger.Error("internal", "client and channel membership out of sync", chname, client.Nick())
1809
+				continue
1810
+			}
1807 1811
 			channelToModes[chname] = status
1808 1812
 		}
1809 1813
 		client.server.accounts.saveChannels(account, channelToModes)

Loading…
Cancel
Save