Fix data race.

This synchronizes access to the (*Client).disconnect channel, which
may change during reconnects.

Fixes #54.
This commit is contained in:
Josh Rickmar 2015-06-15 11:38:25 -04:00
parent ee3a86c44b
commit 77baeb8d79

View file

@ -394,6 +394,16 @@ out:
log.Tracef("RPC client input handler done for %s", c.config.Host)
}
// disconnectChan returns a copy of the current disconnect channel. The channel
// is read protected by the client mutex, and is safe to call while the channel
// is being reassigned during a reconnect.
func (c *Client) disconnectChan() <-chan struct{} {
c.mtx.Lock()
ch := c.disconnect
c.mtx.Unlock()
return ch
}
// wsOutHandler handles all outgoing messages for the websocket connection. It
// uses a buffered channel to serialize output messages while allowing the
// sender to continue running asynchronously. It must be run as a goroutine.
@ -410,7 +420,7 @@ out:
break out
}
case <-c.disconnect:
case <-c.disconnectChan():
break out
}
}
@ -436,7 +446,7 @@ func (c *Client) sendMessage(marshalledJSON []byte) {
// Don't send the message if disconnected.
select {
case c.sendChan <- marshalledJSON:
case <-c.disconnect:
case <-c.disconnectChan():
return
}
}
@ -618,9 +628,9 @@ out:
// has happened.
c.wsConn = wsConn
c.retryCount = 0
c.disconnect = make(chan struct{})
c.mtx.Lock()
c.disconnect = make(chan struct{})
c.disconnected = false
c.mtx.Unlock()