Remove race condition between read go-routine and stop

This commit is contained in:
Ethan Frey 2017-04-11 13:29:49 +02:00
parent a416c37ebd
commit 9d18cbe74e
2 changed files with 8 additions and 3 deletions

View File

@ -86,7 +86,6 @@ func (wsc *WSClient) dial() error {
func (wsc *WSClient) OnStop() { func (wsc *WSClient) OnStop() {
wsc.BaseService.OnStop() wsc.BaseService.OnStop()
wsc.Conn.Close() wsc.Conn.Close()
wsc.Conn = nil
// ResultsCh/ErrorsCh is closed in receiveEventsRoutine. // ResultsCh/ErrorsCh is closed in receiveEventsRoutine.
} }
@ -112,6 +111,9 @@ func (wsc *WSClient) receiveEventsRoutine() {
wsc.ResultsCh <- *response.Result wsc.ResultsCh <- *response.Result
} }
} }
// this must be modified in the same go-routine that reads from the
// connection to avoid race conditions
wsc.Conn = nil
// Cleanup // Cleanup
close(wsc.ResultsCh) close(wsc.ResultsCh)

View File

@ -347,12 +347,15 @@ func NewWSConnection(baseConn *websocket.Conn, funcMap map[string]*RPCFunc, evsw
func (wsc *wsConnection) OnStart() error { func (wsc *wsConnection) OnStart() error {
wsc.BaseService.OnStart() wsc.BaseService.OnStart()
// these must be set before the readRoutine is created, as it may
// call wsc.Stop(), which accesses these timers
wsc.readTimeout = time.NewTimer(time.Second * wsReadTimeoutSeconds)
wsc.pingTicker = time.NewTicker(time.Second * wsPingTickerSeconds)
// Read subscriptions/unsubscriptions to events // Read subscriptions/unsubscriptions to events
go wsc.readRoutine() go wsc.readRoutine()
// Custom Ping handler to touch readTimeout // Custom Ping handler to touch readTimeout
wsc.readTimeout = time.NewTimer(time.Second * wsReadTimeoutSeconds)
wsc.pingTicker = time.NewTicker(time.Second * wsPingTickerSeconds)
wsc.baseConn.SetPingHandler(func(m string) error { wsc.baseConn.SetPingHandler(func(m string) error {
// NOTE: https://github.com/gorilla/websocket/issues/97 // NOTE: https://github.com/gorilla/websocket/issues/97
go wsc.baseConn.WriteControl(websocket.PongMessage, []byte(m), time.Now().Add(time.Second*wsWriteTimeoutSeconds)) go wsc.baseConn.WriteControl(websocket.PongMessage, []byte(m), time.Now().Add(time.Second*wsWriteTimeoutSeconds))