livereload: Fix data race in close
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sat, 29 Apr 2017 23:10:03 +0000 (01:10 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sat, 29 Apr 2017 23:10:57 +0000 (01:10 +0200)
Fixes #2625

livereload/connection.go
livereload/hub.go

index 6e31b1baf43f0efdeaa70f876d8e4b1e2154fae9..4e94e2ee0cf6ec6b894b9370ae855d39e717b4fd 100644 (file)
@@ -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() {
index 359bac3f1612437d3fdbcc553723ad1137fcb6b3..8ab6083addd3585e90d0272293907913b2fcb3a2 100644 (file)
@@ -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()
                                }
                        }
                }