From 355736ec357c81dfb2eb6851ee019d407090c5ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Sun, 30 Apr 2017 01:10:03 +0200 Subject: [PATCH] livereload: Fix data race in close Fixes #2625 --- livereload/connection.go | 11 +++++++++++ livereload/hub.go | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/livereload/connection.go b/livereload/connection.go index 6e31b1baf..4e94e2ee0 100644 --- a/livereload/connection.go +++ b/livereload/connection.go @@ -15,6 +15,7 @@ package livereload import ( "bytes" + "sync" "github.com/gorilla/websocket" ) @@ -25,6 +26,16 @@ type connection struct { // Buffered channel of outbound messages. send chan []byte + + // There is a potential data race, especially visible with large files. + // This is protected by synchronisation of the send channel's close. + closer sync.Once +} + +func (c *connection) close() { + c.closer.Do(func() { + close(c.send) + }) } func (c *connection) reader() { diff --git a/livereload/hub.go b/livereload/hub.go index 359bac3f1..8ab6083ad 100644 --- a/livereload/hub.go +++ b/livereload/hub.go @@ -41,14 +41,14 @@ func (h *hub) run() { h.connections[c] = true case c := <-h.unregister: delete(h.connections, c) - close(c.send) + c.close() case m := <-h.broadcast: for c := range h.connections { select { case c.send <- m: default: delete(h.connections, c) - close(c.send) + c.close() } } }