mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-10 22:19:31 +01:00
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.
This commit is contained in:
parent
cec3416eae
commit
300d02bd9c
@ -221,11 +221,7 @@ func (channel *Channel) modeStringNoLock(client *Client) (str string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (channel *Channel) IsFull() bool {
|
func (channel *Channel) IsFull() bool {
|
||||||
channel.membersMutex.RLock()
|
return (channel.userLimit > 0) && (uint64(len(channel.members)) >= channel.userLimit)
|
||||||
defer channel.membersMutex.RUnlock()
|
|
||||||
|
|
||||||
return (channel.userLimit > 0) &&
|
|
||||||
(uint64(len(channel.members)) >= channel.userLimit)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (channel *Channel) CheckKey(key string) bool {
|
func (channel *Channel) CheckKey(key string) bool {
|
||||||
@ -234,11 +230,11 @@ func (channel *Channel) CheckKey(key string) bool {
|
|||||||
|
|
||||||
func (channel *Channel) Join(client *Client, key string) {
|
func (channel *Channel) Join(client *Client, key string) {
|
||||||
channel.membersMutex.Lock()
|
channel.membersMutex.Lock()
|
||||||
|
defer channel.membersMutex.Unlock()
|
||||||
if channel.members.Has(client) {
|
if channel.members.Has(client) {
|
||||||
// already joined, no message?
|
// already joined, no message needs to be sent
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
channel.membersMutex.Unlock()
|
|
||||||
|
|
||||||
if channel.IsFull() {
|
if channel.IsFull() {
|
||||||
client.Send(nil, client.server.name, ERR_CHANNELISFULL, channel.name, "Cannot join channel (+l)")
|
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) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
channel.membersMutex.Lock()
|
|
||||||
defer channel.membersMutex.Unlock()
|
|
||||||
if channel.lists[BanMask].Match(client.nickMaskCasefolded) &&
|
if channel.lists[BanMask].Match(client.nickMaskCasefolded) &&
|
||||||
!isInvited &&
|
!isInvited &&
|
||||||
!channel.lists[ExceptMask].Match(client.nickMaskCasefolded) {
|
!channel.lists[ExceptMask].Match(client.nickMaskCasefolded) {
|
||||||
@ -326,8 +320,8 @@ func (channel *Channel) Join(client *Client, key string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (channel *Channel) Part(client *Client, message string) {
|
func (channel *Channel) Part(client *Client, message string) {
|
||||||
channel.membersMutex.RLock()
|
channel.membersMutex.Lock()
|
||||||
defer channel.membersMutex.RUnlock()
|
defer channel.membersMutex.Unlock()
|
||||||
|
|
||||||
if !channel.members.Has(client) {
|
if !channel.members.Has(client) {
|
||||||
client.Send(nil, client.server.name, ERR_NOTONCHANNEL, channel.name, "You're not on that channel")
|
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
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (channel *Channel) Quit(client *Client) {
|
// Quit removes the given client from the channel, and also updates friends with the latest client list.
|
||||||
|
func (channel *Channel) Quit(client *Client, friends *ClientSet) {
|
||||||
channel.membersMutex.Lock()
|
channel.membersMutex.Lock()
|
||||||
defer channel.membersMutex.Unlock()
|
defer channel.membersMutex.Unlock()
|
||||||
|
|
||||||
channel.quitNoMutex(client)
|
channel.quitNoMutex(client)
|
||||||
|
|
||||||
|
for friend := range channel.members {
|
||||||
|
friends.Add(friend)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (channel *Channel) quitNoMutex(client *Client) {
|
func (channel *Channel) quitNoMutex(client *Client) {
|
||||||
|
@ -482,7 +482,7 @@ func (client *Client) destroy() {
|
|||||||
|
|
||||||
// clean up channels
|
// clean up channels
|
||||||
for channel := range client.channels {
|
for channel := range client.channels {
|
||||||
channel.Quit(client)
|
channel.Quit(client, &friends)
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up server
|
// clean up server
|
||||||
|
Loading…
Reference in New Issue
Block a user