internal/server: data race on broadcast set
The set of clients signed up for event notifications (tracked within the clients map) is accessed from within HTTP handlers. At least one of those accesses is a write operation.
This results in a data race, as HTTP handlers execute concurrently (the
net/http
server kicks off goroutines in response to client requests).
When building stream-server with the race detector enabled (-race
flag),
matching diagnostics are emitted to stderr upon triggering the race:
WARNING: DATA RACE
Write at 0x00c000480000 by goroutine 37:
runtime.mapassign_fast64()
/home/ls/go/src/runtime/map_fast64.go:92 +0x0
stream-server/internal/server.displayEventsHandler()
/home/ls/src/code.fbi.h-da.de/stream-server/stream-server/internal/server/display.go:153 +0xb6
stream-server/internal/server.ListenAndServe.func2()
/home/ls/src/code.fbi.h-da.de/stream-server/stream-server/internal/server/server.go:30 +0xed
[…]
Previous write at 0x00c000480000 by goroutine 36:
runtime.mapassign_fast64()
/home/ls/go/src/runtime/map_fast64.go:92 +0x0
stream-server/internal/server.displayEventsHandler()
/home/ls/src/code.fbi.h-da.de/stream-server/stream-server/internal/server/display.go:153 +0xb6
stream-server/internal/server.ListenAndServe.func2()
/home/ls/src/code.fbi.h-da.de/stream-server/stream-server/internal/server/server.go:30 +0xed
[…]
Something akin to the following shell snippet reliably triggers the race on my local machine but YMMV, of course.
exec </dev/null >&0 2>&0 # stfu
curl -H 'Accept: text/event-stream' http://127.0.0.1:8080/display &
curl -H 'Accept: text/event-stream' http://127.0.0.1:8080/display &
curl -H 'Accept: text/event-stream' http://127.0.0.1:8080/display &
Going to send a merge request with a proposed fix (just wrap a mutex around the map) in a few minutes.