I have a WebSocket client that currently has a data race when connecting to the WS server. The WS client works by connecting to the server, listening to the server connection, and then subscribing to specific WS endpoints.
If it matters, I'm using a custom wrapper that I created on top of the SAC007 WS client (I've made a few small modifications to the SAC007 client as well, in order to fit my needs better, but nothing that should cause a data race) and currently trying to understand what I'm doing wrong to get a race, but have no luck with understanding the issue so far. Would appreciate any help understanding what I'm doing wrong
Here is my main program:
func main() {
// check if in production or testing mode
var testing bool = true
args := os.Args
initClient(args, &testing, &stored_data.Base_currency)
// concurrency handling
comms := make(chan os.Signal, 1)
signal.Notify(comms, os.Interrupt, syscall.SIGTERM)
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
var wg sync.WaitGroup
// set ohlc interval(s) and pair(s)
OHLCinterval := []int{1, 5}
pairs := []string{"BTC/" + stored_data.Base_currency, "ETH/" + stored_data.Base_currency, "EOS/" + stored_data.Base_currency}
// create ws connections
wg.Add(1)
pubSocket, err := ws_client.ConnectToServer(&wg, "public", testing)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// create websocket channel(s)
pubCh := make(chan interface{})
defer close(pubCh)
// listen to websocket connection(s)
wg.Add(1)
go pubSocket.PubListen(ctx, &wg, pubCh, testing)
// connect to data streams. goes through all interval values
for _, interval := range OHLCinterval {
wg.Add(1)
go pubSocket.SubscribeToOHLC(ctx, &wg, pairs, interval)
}
// code continues from here but is irrelevant to the data race
}
Custom functions built in WS wrapper:
func ConnectToServer(wg *sync.WaitGroup, server string, testing bool) (*Socket, error) {
defer wg.Done()
if server != "public" && server != "private" {
return nil, errors.New("Server must be 'public' or 'private'")
}
var socket Socket
if server == "public" {
socket = New(stored_data.Pub_ws_url)
} else {
socket = New(stored_data.Priv_ws_url)
}
socket.OnConnected = func(socket Socket) {
log.Println("Connected to server")
}
socket.OnTextMessage = func(message string, socket Socket) {
pubJsonDecoder(message, testing)
log.Println(message)
}
socket.Connect()
return &socket, nil
}
func (socket *Socket) PubListen(ctx context.Context, wg *sync.WaitGroup, ch chan interface{}, testing bool) {
defer wg.Done()
defer socket.Close()
var res interface{}
socket.OnTextMessage = func(message string, socket Socket) {
res = pubJsonDecoder(message, testing)
ch <- res
}
<-ctx.Done()
log.Println("closing public socket")
return
}
func (socket *Socket) SubscribeToOHLC(ctx context.Context, wg *sync.WaitGroup, pairs []string, interval int) {
defer wg.Done()
sub, _ := json.Marshal(&types.Subscribe{
Event: "subscribe",
Subscription: &types.OHLCSubscription{
Interval: interval,
Name: "ohlc",
},
Pair: pairs,
})
socket.SendBinary(sub)
<-ctx.Done()
}
Data Race message 1:
==================
WARNING: DATA RACE
Read at 0x00c0001145d8 by goroutine 19:
kraken_client/ws_client.(*Socket).Connect.func4()
/Users/grantcanty/go/src/kraken_client/ws_client/websocket_client.go:156 +0x3b5
Previous write at 0x00c0001145d8 by goroutine 20:
kraken_client/ws_client.(*Socket).PubListen()
/Users/grantcanty/go/src/kraken_client/ws_client/websocket_wrapper.go:73 +0x234
main.main.func4()
/Users/grantcanty/go/src/kraken_client/main.go:79 +0x8d
Goroutine 19 (running) created at:
kraken_client/ws_client.(*Socket).Connect()
/Users/grantcanty/go/src/kraken_client/ws_client/websocket_client.go:136 +0xc75
kraken_client/ws_client.ConnectToServer()
/Users/grantcanty/go/src/kraken_client/ws_client/websocket_wrapper.go:39 +0x6a4
main.main()
/Users/grantcanty/go/src/kraken_client/main.go:59 +0x3d4
Goroutine 20 (running) created at:
main.main()
/Users/grantcanty/go/src/kraken_client/main.go:79 +0x6e4
==================
Data race message 2:
==================
WARNING: DATA RACE
Write at 0x00c000300000 by goroutine 19:
kraken_client/ws_client.(*Socket).PubListen.func1()
/Users/grantcanty/go/src/kraken_client/ws_client/websocket_wrapper.go:74 +0x84
kraken_client/ws_client.(*Socket).Connect.func4()
/Users/grantcanty/go/src/kraken_client/ws_client/websocket_client.go:157 +0x4ab
Previous write at 0x00c000300000 by goroutine 20:
kraken_client/ws_client.(*Socket).PubListen()
/Users/grantcanty/go/src/kraken_client/ws_client/websocket_wrapper.go:71 +0x111
main.main.func4()
/Users/grantcanty/go/src/kraken_client/main.go:79 +0x8d
Goroutine 19 (running) created at:
kraken_client/ws_client.(*Socket).Connect()
/Users/grantcanty/go/src/kraken_client/ws_client/websocket_client.go:136 +0xc75
kraken_client/ws_client.ConnectToServer()
/Users/grantcanty/go/src/kraken_client/ws_client/websocket_wrapper.go:39 +0x6a4
main.main()
/Users/grantcanty/go/src/kraken_client/main.go:59 +0x3d4
Goroutine 20 (running) created at:
main.main()
/Users/grantcanty/go/src/kraken_client/main.go:79 +0x6e4
==================