Eliminate client close deadlocks. (#1833)

This commit is contained in:
funkyhippo 2022-04-15 21:30:05 -05:00 committed by GitHub
parent a825a831fe
commit 79ca6e04f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 15 additions and 6 deletions

View file

@ -3,6 +3,7 @@ package chat
import (
"bytes"
"encoding/json"
"sync"
"time"
log "github.com/sirupsen/logrus"
@ -17,6 +18,7 @@ import (
// Client represents a single chat client.
type Client struct {
mu sync.RWMutex
id uint
accessToken string
conn *websocket.Conn
@ -152,11 +154,13 @@ func (c *Client) writePump() {
// Optimization: Send multiple events in a single websocket message.
// Add queued chat messages to the current websocket message.
c.mu.RLock()
n := len(c.send)
for i := 0; i < n; i++ {
_, _ = w.Write(newline)
_, _ = w.Write(<-c.send)
}
c.mu.RUnlock()
if err := w.Close(); err != nil {
return
@ -177,9 +181,12 @@ func (c *Client) handleEvent(data []byte) {
func (c *Client) close() {
log.Traceln("client closed:", c.User.DisplayName, c.id, c.IPAddress)
_ = c.conn.Close()
c.server.unregister <- c.id
c.mu.Lock()
defer c.mu.Unlock()
if c.send != nil {
_ = c.conn.Close()
c.server.unregister <- c.id
close(c.send)
c.send = nil
}
@ -214,6 +221,9 @@ func (c *Client) sendPayload(payload interface{}) {
return
}
c.mu.RLock()
defer c.mu.RUnlock()
if c.send != nil {
c.send <- data
}

View file

@ -231,8 +231,8 @@ func (s *Server) Broadcast(payload events.EventPayload) error {
return err
}
s.mu.Lock()
defer s.mu.Unlock()
s.mu.RLock()
defer s.mu.RUnlock()
for _, client := range s.clients {
if client == nil {
@ -242,8 +242,7 @@ func (s *Server) Broadcast(payload events.EventPayload) error {
select {
case client.send <- data:
default:
client.close()
delete(s.clients, client.id)
go client.close()
}
}