From 9d18cbe74e66f875afa36d2fa3be280e4a2dc9e6 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 11 Apr 2017 13:29:49 +0200 Subject: [PATCH] Remove race condition between read go-routine and stop --- client/ws_client.go | 4 +++- server/handlers.go | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/client/ws_client.go b/client/ws_client.go index 9ed2be8c..9933ab07 100644 --- a/client/ws_client.go +++ b/client/ws_client.go @@ -86,7 +86,6 @@ func (wsc *WSClient) dial() error { func (wsc *WSClient) OnStop() { wsc.BaseService.OnStop() wsc.Conn.Close() - wsc.Conn = nil // ResultsCh/ErrorsCh is closed in receiveEventsRoutine. } @@ -112,6 +111,9 @@ func (wsc *WSClient) receiveEventsRoutine() { 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 close(wsc.ResultsCh) diff --git a/server/handlers.go b/server/handlers.go index 5b600850..573696fb 100644 --- a/server/handlers.go +++ b/server/handlers.go @@ -347,12 +347,15 @@ func NewWSConnection(baseConn *websocket.Conn, funcMap map[string]*RPCFunc, evsw func (wsc *wsConnection) OnStart() error { 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 go wsc.readRoutine() // 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 { // NOTE: https://github.com/gorilla/websocket/issues/97 go wsc.baseConn.WriteControl(websocket.PongMessage, []byte(m), time.Now().Add(time.Second*wsWriteTimeoutSeconds))