Просмотр исходного кода

channel: Kill a race condition that locked up the server.

Specifically, if you joined a channel while someone else was trying to part. the Join method would grab the lock, the Quit method would queue to grab the lock, the Join method would unlock and then try to regrab the lock, and it would get into a situation where nobody would have the lock and everyone would be waiting for it.

This caused weird oddities with clients.
tags/v0.7.0
Daniel Oaks 7 лет назад
Родитель
Сommit
300d02bd9c
2 измененных файлов: 12 добавлений и 13 удалений
  1. 11
    12
      irc/channel.go
  2. 1
    1
      irc/client.go

+ 11
- 12
irc/channel.go Просмотреть файл

@@ -221,11 +221,7 @@ func (channel *Channel) modeStringNoLock(client *Client) (str string) {
221 221
 }
222 222
 
223 223
 func (channel *Channel) IsFull() bool {
224
-	channel.membersMutex.RLock()
225
-	defer channel.membersMutex.RUnlock()
226
-
227
-	return (channel.userLimit > 0) &&
228
-		(uint64(len(channel.members)) >= channel.userLimit)
224
+	return (channel.userLimit > 0) && (uint64(len(channel.members)) >= channel.userLimit)
229 225
 }
230 226
 
231 227
 func (channel *Channel) CheckKey(key string) bool {
@@ -234,11 +230,11 @@ func (channel *Channel) CheckKey(key string) bool {
234 230
 
235 231
 func (channel *Channel) Join(client *Client, key string) {
236 232
 	channel.membersMutex.Lock()
233
+	defer channel.membersMutex.Unlock()
237 234
 	if channel.members.Has(client) {
238
-		// already joined, no message?
235
+		// already joined, no message needs to be sent
239 236
 		return
240 237
 	}
241
-	channel.membersMutex.Unlock()
242 238
 
243 239
 	if channel.IsFull() {
244 240
 		client.Send(nil, client.server.name, ERR_CHANNELISFULL, channel.name, "Cannot join channel (+l)")
@@ -256,8 +252,6 @@ func (channel *Channel) Join(client *Client, key string) {
256 252
 		return
257 253
 	}
258 254
 
259
-	channel.membersMutex.Lock()
260
-	defer channel.membersMutex.Unlock()
261 255
 	if channel.lists[BanMask].Match(client.nickMaskCasefolded) &&
262 256
 		!isInvited &&
263 257
 		!channel.lists[ExceptMask].Match(client.nickMaskCasefolded) {
@@ -326,8 +320,8 @@ func (channel *Channel) Join(client *Client, key string) {
326 320
 }
327 321
 
328 322
 func (channel *Channel) Part(client *Client, message string) {
329
-	channel.membersMutex.RLock()
330
-	defer channel.membersMutex.RUnlock()
323
+	channel.membersMutex.Lock()
324
+	defer channel.membersMutex.Unlock()
331 325
 
332 326
 	if !channel.members.Has(client) {
333 327
 		client.Send(nil, client.server.name, ERR_NOTONCHANNEL, channel.name, "You're not on that channel")
@@ -644,11 +638,16 @@ func (channel *Channel) applyModeMask(client *Client, mode Mode, op ModeOp, mask
644 638
 	return false
645 639
 }
646 640
 
647
-func (channel *Channel) Quit(client *Client) {
641
+// Quit removes the given client from the channel, and also updates friends with the latest client list.
642
+func (channel *Channel) Quit(client *Client, friends *ClientSet) {
648 643
 	channel.membersMutex.Lock()
649 644
 	defer channel.membersMutex.Unlock()
650 645
 
651 646
 	channel.quitNoMutex(client)
647
+
648
+	for friend := range channel.members {
649
+		friends.Add(friend)
650
+	}
652 651
 }
653 652
 
654 653
 func (channel *Channel) quitNoMutex(client *Client) {

+ 1
- 1
irc/client.go Просмотреть файл

@@ -482,7 +482,7 @@ func (client *Client) destroy() {
482 482
 
483 483
 	// clean up channels
484 484
 	for channel := range client.channels {
485
-		channel.Quit(client)
485
+		channel.Quit(client, &friends)
486 486
 	}
487 487
 
488 488
 	// clean up server

Загрузка…
Отмена
Сохранить