Skip to content

Commit 6d65dd7

Browse files
committed
ethstats: avoid concurrent write on websocket, fixes ethereum#21403
1 parent 9c2ac6f commit 6d65dd7

File tree

1 file changed

+18
-0
lines changed

1 file changed

+18
-0
lines changed

ethstats/ethstats.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"runtime"
2929
"strconv"
3030
"strings"
31+
"sync"
3132
"time"
3233

3334
"github.com/ethereum/go-ethereum/common"
@@ -80,6 +81,8 @@ type Service struct {
8081

8182
pongCh chan struct{} // Pong notifications are fed into this channel
8283
histCh chan []uint64 // History request block numbers are fed into this channel
84+
85+
connMu sync.Mutex // Mutex to prevent concurrent write on the websocket connection
8386
}
8487

8588
// New returns a monitoring service ready for stats reporting.
@@ -306,10 +309,13 @@ func (s *Service) readLoop(conn *websocket.Conn) {
306309
// If the network packet is a system ping, respond to it directly
307310
var ping string
308311
if err := json.Unmarshal(blob, &ping); err == nil && strings.HasPrefix(ping, "primus::ping::") {
312+
s.connMu.Lock()
309313
if err := conn.WriteJSON(strings.Replace(ping, "ping", "pong", -1)); err != nil {
314+
s.connMu.Unlock()
310315
log.Warn("Failed to respond to system ping message", "err", err)
311316
return
312317
}
318+
s.connMu.Unlock()
313319
continue
314320
}
315321
// Not a system ping, try to decode an actual state message
@@ -432,6 +438,8 @@ func (s *Service) login(conn *websocket.Conn) error {
432438
login := map[string][]interface{}{
433439
"emit": {"hello", auth},
434440
}
441+
s.connMu.Lock()
442+
defer s.connMu.Unlock()
435443
if err := conn.WriteJSON(login); err != nil {
436444
return err
437445
}
@@ -474,6 +482,8 @@ func (s *Service) reportLatency(conn *websocket.Conn) error {
474482
"clientTime": start.String(),
475483
}},
476484
}
485+
s.connMu.Lock()
486+
defer s.connMu.Unlock()
477487
if err := conn.WriteJSON(ping); err != nil {
478488
return err
479489
}
@@ -547,6 +557,8 @@ func (s *Service) reportBlock(conn *websocket.Conn, block *types.Block) error {
547557
report := map[string][]interface{}{
548558
"emit": {"block", stats},
549559
}
560+
s.connMu.Lock()
561+
defer s.connMu.Unlock()
550562
return conn.WriteJSON(report)
551563
}
552564

@@ -661,6 +673,8 @@ func (s *Service) reportHistory(conn *websocket.Conn, list []uint64) error {
661673
report := map[string][]interface{}{
662674
"emit": {"history", stats},
663675
}
676+
s.connMu.Unlock()
677+
defer s.connMu.Unlock()
664678
return conn.WriteJSON(report)
665679
}
666680

@@ -691,6 +705,8 @@ func (s *Service) reportPending(conn *websocket.Conn) error {
691705
report := map[string][]interface{}{
692706
"emit": {"pending", stats},
693707
}
708+
s.connMu.Lock()
709+
defer s.connMu.Unlock()
694710
return conn.WriteJSON(report)
695711
}
696712

@@ -746,5 +762,7 @@ func (s *Service) reportStats(conn *websocket.Conn) error {
746762
report := map[string][]interface{}{
747763
"emit": {"stats", stats},
748764
}
765+
s.connMu.Lock()
766+
defer s.connMu.Unlock()
749767
return conn.WriteJSON(report)
750768
}

0 commit comments

Comments
 (0)