1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-07-05 18:48:31 +00:00

Fix panic sending on closed client.MessageChannel

This commit is contained in:
Kane York 2015-10-29 01:23:58 -07:00
parent 601b5501a7
commit 33bf762a00
3 changed files with 35 additions and 22 deletions

View file

@ -85,22 +85,20 @@ func HandleReady(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (r
client.MakePendingRequests = nil client.MakePendingRequests = nil
client.Mutex.Unlock() client.Mutex.Unlock()
if disconnectAt == 0 { go func() {
// backlog only client.MsgChannelKeepalive.RLock()
go func() { if client.MessageChannel == nil {
client.MessageChannel <- ClientMessage{MessageID: msg.MessageID, Command: SuccessCommand} return
SendBacklogForNewClient(client) }
}()
return ClientMessage{Command: AsyncResponseCommand}, nil client.MessageChannel <- ClientMessage{MessageID: msg.MessageID, Command: SuccessCommand}
} else { SendBacklogForNewClient(client)
// backlog and timed if disconnectAt != 0 {
go func() {
client.MessageChannel <- ClientMessage{MessageID: msg.MessageID, Command: SuccessCommand}
SendBacklogForNewClient(client)
SendTimedBacklogMessages(client, time.Unix(disconnectAt, 0)) SendTimedBacklogMessages(client, time.Unix(disconnectAt, 0))
}() }
return ClientMessage{Command: AsyncResponseCommand}, nil client.MsgChannelKeepalive.RUnlock()
} }()
return ClientMessage{Command: AsyncResponseCommand}, nil
} }
func HandleSetUser(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { func HandleSetUser(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) {
@ -193,9 +191,13 @@ func GetSubscriptionBacklog(conn *websocket.Conn, client *ClientInfo) {
} }
// Deliver to client // Deliver to client
for _, msg := range messages { client.MsgChannelKeepalive.RLock()
client.MessageChannel <- msg if client.MessageChannel != nil {
for _, msg := range messages {
client.MessageChannel <- msg
}
} }
client.MsgChannelKeepalive.RUnlock()
} }
func HandleSurvey(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { func HandleSurvey(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) {
@ -318,11 +320,15 @@ func HandleRemoteCommand(conn *websocket.Conn, client *ClientInfo, msg ClientMes
go func(conn *websocket.Conn, msg ClientMessage, authInfo AuthInfo) { go func(conn *websocket.Conn, msg ClientMessage, authInfo AuthInfo) {
resp, err := RequestRemoteDataCached(string(msg.Command), msg.origArguments, authInfo) resp, err := RequestRemoteDataCached(string(msg.Command), msg.origArguments, authInfo)
if err != nil { client.MsgChannelKeepalive.RLock()
client.MessageChannel <- ClientMessage{MessageID: msg.MessageID, Command: ErrorCommand, Arguments: err.Error()} if client.MessageChannel != nil {
} else { if err != nil {
client.MessageChannel <- ClientMessage{MessageID: msg.MessageID, Command: SuccessCommand, origArguments: resp} client.MessageChannel <- ClientMessage{MessageID: msg.MessageID, Command: ErrorCommand, Arguments: err.Error()}
} else {
client.MessageChannel <- ClientMessage{MessageID: msg.MessageID, Command: SuccessCommand, origArguments: resp}
}
} }
client.MsgChannelKeepalive.RUnlock()
}(conn, msg, client.AuthInfo) }(conn, msg, client.AuthInfo)
return ClientMessage{Command: AsyncResponseCommand}, nil return ClientMessage{Command: AsyncResponseCommand}, nil

View file

@ -247,6 +247,10 @@ RunLoop:
// Stop getting messages... // Stop getting messages...
UnsubscribeAll(&client) UnsubscribeAll(&client)
client.MsgChannelKeepalive.Lock()
client.MessageChannel = nil
client.MsgChannelKeepalive.Unlock()
// And finished. // And finished.
// Close the channel so the draining goroutine can finish, too. // Close the channel so the draining goroutine can finish, too.
close(_serverMessageChan) close(_serverMessageChan)

View file

@ -85,9 +85,12 @@ type ClientInfo struct {
MakePendingRequests *time.Timer MakePendingRequests *time.Timer
// Server-initiated messages should be sent here // Server-initiated messages should be sent here
// Never nil. // This field will be nil before it is closed.
MessageChannel chan<- ClientMessage MessageChannel chan<- ClientMessage
// Take a read-lock on this before checking whether MessageChannel is nil.
MsgChannelKeepalive sync.RWMutex
// The number of pings sent without a response // The number of pings sent without a response
pingCount int pingCount int
} }