Skip to content

Commit 48c1157

Browse files
committed
prevent race condition between net/http closing a connection and c.flush()
1 parent 422a5ad commit 48c1157

File tree

1 file changed

+13
-3
lines changed

1 file changed

+13
-3
lines changed

client.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,18 @@ func NewClient(w http.ResponseWriter, req *http.Request) *Client {
5656
return c
5757
}
5858

59+
func (c *Client) Closed() bool {
60+
c.lock.Lock()
61+
defer c.lock.Unlock()
62+
return c.closed
63+
}
64+
5965
// Send queues an event to be sent to the client.
6066
// This does not block until the event has been sent,
6167
// however it could block if the event queue is full.
6268
// Returns an error if the Client has disconnected
6369
func (c *Client) Send(ev Event) error {
64-
if c.closed {
70+
if c.Closed() {
6571
return io.ErrClosedPipe
6672
}
6773
c.events <- ev
@@ -73,7 +79,7 @@ func (c *Client) Send(ev Event) error {
7379
// Returns true if blocked
7480
// Returns an error if the Client has disconnected
7581
func (c *Client) SendNonBlocking(ev Event) (bool, error) {
76-
if c.closed {
82+
if c.Closed() {
7783
return false, io.ErrClosedPipe
7884
}
7985
select {
@@ -105,7 +111,9 @@ func (c *Client) run() {
105111
case ev, ok := <-c.events:
106112
// check for shutdown
107113
if !ok {
114+
c.lock.Lock()
108115
c.closed = true
116+
c.lock.Unlock()
109117
c.waiter.Done()
110118
return
111119
}
@@ -119,7 +127,9 @@ func (c *Client) run() {
119127
c.lock.Unlock()
120128

121129
case <-done:
130+
c.lock.Lock()
122131
c.closed = true
132+
c.lock.Unlock()
123133
c.waiter.Done()
124134
return
125135
}
@@ -131,7 +141,7 @@ func (c *Client) run() {
131141
func (c *Client) flush() {
132142
c.lock.Lock()
133143
defer c.lock.Unlock()
134-
if c.closed {
144+
if c.closed || c.ctx.Err() != nil {
135145
return
136146
}
137147
c.flushing = nil

0 commit comments

Comments
 (0)