HuobiRDCenter/huobi_Golang

panic: concurrent write to websocket connection

Closed this issue · 5 comments

i subscribe websocket market data and receive realtime kline, Client.Subscribe("btcusdt", "1min", "2118").
i also obtain historical kline periodically by a time.ticker goroutine, Client.Request(xxxxxxx)
but i got a panic finally after running a period of time,

panic: concurrent write to websocket connection

goroutine 33 [running]:
github.com/gorilla/websocket.(*messageWriter).flushFrame(0xc00007d260, 0xc000170001, 0x0, 0x0, 0x0, 0x7f01d726d108, 0x0)
        F:/go/pkg/mod/github.com/gorilla/websocket@v1.4.1/conn.go:610 +0x5e9
github.com/gorilla/websocket.(*messageWriter).Close(0xc00007d260, 0x0, 0xc0006c5de8)
        F:/go/pkg/mod/github.com/gorilla/websocket@v1.4.1/conn.go:724 +0x62
github.com/gorilla/websocket.(*Conn).beginMessage(0xc00054b4a0, 0xc000170030, 0x1, 0x0, 0xc0006c5e40)
        F:/go/pkg/mod/github.com/gorilla/websocket@v1.4.1/conn.go:473 +0x26d
github.com/gorilla/websocket.(*Conn).NextWriter(0xc00054b4a0, 0x1, 0x9, 0xbf6400, 0xc000328060, 0x20)
        F:/go/pkg/mod/github.com/gorilla/websocket@v1.4.1/conn.go:513 +0x53
github.com/gorilla/websocket.(*Conn).WriteMessage(0xc00054b4a0, 0x1, 0xc000328060, 0x17, 0x20, 0x20, 0x17)
        F:/go/pkg/mod/github.com/gorilla/websocket@v1.4.1/conn.go:766 +0x6e
github.com/huobirdcenter/huobi_golang/pkg/client/websocketclientbase.(*WebSocketClientBase).readLoop(0xc00006e360)
        F:/go/pkg/mod/github.com/huobirdcenter/huobi_golang@v0.0.0-20200420092918-b5239dd6398e/pkg/client/websocketclientbase/websocketclientbase.go:222 +0x528
created by github.com/huobirdcenter/huobi_golang/pkg/client/websocketclientbase.(*WebSocketClientBase).startReadLoop
        F:/go/pkg/mod/github.com/huobirdcenter/huobi_golang@v0.0.0-20200420092918-b5239dd6398e/pkg/client/websocketclientbase/websocketclientbase.go:174 +0x3f

i think the reason is time.Ticker goroutine and ping pong in "startReadLoop --> readLoop" write websocket simultaneous, how to solve it?

@titilami thanks for the feedback, I had a look the source code of websocket and I think we can find a solution. I will do more test and fix this.

@eynzhang thx, i have multi goroutines to send websocket request. These goroutines may call WebSocketClientBase.conn.WriteMessage simultaneous at sometime
.

@titilami I think we need to handle it ourselves in SDK, the gorilla websocket doesn’t support concurrent write message, see below words from their documentation:

https://github.com/gorilla/websocket/blob/master/doc.go

Concurrency

Connections support one concurrent reader and one concurrent writer.

Applications are responsible for ensuring that no more than one goroutine
calls the write methods (NextWriter, SetWriteDeadline, WriteMessage,
WriteJSON, EnableWriteCompression, SetCompressionLevel) concurrently and
that no more than one goroutine calls the read methods (NextReader,
SetReadDeadline, ReadMessage, ReadJSON, SetPongHandler, SetPingHandler)
concurrently.

The Close and WriteControl methods can be called concurrently with all other
methods.

@titilami please get the lates update from master branch, the mutex is introduced to support concurrently subscribing. I tested it and it works well. You can refer to the new added traderexample.