Data race in WebSocket tunnel code
==================
WARNING: DATA RACE
Write at 0x00c0002cccc0 by goroutine 389:
github.com/gorilla/websocket.(*Conn).SetWriteDeadline()
/Users/mike/go/pkg/mod/github.com/gorilla/websocket@v1.5.4-0.20250319132907-e064f32e3674/conn.go:797 +0x58
gitlab.com/gitlab-org/gitlab-runner/router/internal/wstunnel.(*netConn).SetWriteDeadline()
/Users/mike/src/gitlab-runner/router/internal/wstunnel/netconn.go:120 +0x34
google.golang.org/grpc/internal/transport.(*http2Client).Close()
/Users/mike/go/pkg/mod/google.golang.org/grpc@v1.78.0/internal/transport/http2_client.go:997 +0x84
google.golang.org/grpc.(*addrConn).tearDown()
/Users/mike/go/pkg/mod/google.golang.org/grpc@v1.78.0/clientconn.go:1705 +0x354
google.golang.org/grpc.(*ClientConn).Close.func2()
/Users/mike/go/pkg/mod/google.golang.org/grpc@v1.78.0/clientconn.go:1227 +0x80
google.golang.org/grpc.(*ClientConn).Close.gowrap1()
/Users/mike/go/pkg/mod/google.golang.org/grpc@v1.78.0/clientconn.go:1228 +0x40
Previous read at 0x00c0002cccc0 by goroutine 57:
github.com/gorilla/websocket.(*messageWriter).flushFrame()
/Users/mike/go/pkg/mod/github.com/gorilla/websocket@v1.5.4-0.20250319132907-e064f32e3674/conn.go:630 +0x748
github.com/gorilla/websocket.(*messageWriter).Close()
/Users/mike/go/pkg/mod/github.com/gorilla/websocket@v1.5.4-0.20250319132907-e064f32e3674/conn.go:740 +0x84
github.com/gorilla/websocket.(*Conn).WriteMessage()
/Users/mike/go/pkg/mod/github.com/gorilla/websocket@v1.5.4-0.20250319132907-e064f32e3674/conn.go:789 +0x1d4
gitlab.com/gitlab-org/gitlab-runner/router/internal/wstunnel.(*netConn).Write()
/Users/mike/src/gitlab-runner/router/internal/wstunnel/netconn.go:56 +0x54
google.golang.org/grpc/internal/transport.(*bufWriter).flushKeepBuffer()
/Users/mike/go/pkg/mod/google.golang.org/grpc@v1.78.0/internal/transport/http_util.go:366 +0xbc
google.golang.org/grpc/internal/transport.(*bufWriter).Flush()
/Users/mike/go/pkg/mod/google.golang.org/grpc@v1.78.0/internal/transport/http_util.go:349 +0x28
google.golang.org/grpc/internal/transport.(*loopyWriter).run()
/Users/mike/go/pkg/mod/google.golang.org/grpc@v1.78.0/internal/transport/controlbuf.go:642 +0xcc
google.golang.org/grpc/internal/transport.NewHTTP2Client.func6()
/Users/mike/go/pkg/mod/google.golang.org/grpc@v1.78.0/internal/transport/http2_client.go:469 +0x184
Goroutine 389 (running) created at:
google.golang.org/grpc.(*ClientConn).Close()
/Users/mike/go/pkg/mod/google.golang.org/grpc@v1.78.0/clientconn.go:1225 +0x2e4
gitlab.com/gitlab-org/gitlab-runner/router.(*connHolder).forceClose()
/Users/mike/src/gitlab-runner/router/client_conn_factory.go:101 +0x80
gitlab.com/gitlab-org/gitlab-runner/router.(*ClientConnFactory).Shutdown()
/Users/mike/src/gitlab-runner/router/client_conn_factory.go:180 +0xcc
gitlab.com/gitlab-org/gitlab-runner/router.(*Client).Shutdown()
/Users/mike/src/gitlab-runner/router/client.go:53 +0x48
gitlab.com/gitlab-org/gitlab-runner/router.(*Client).Shutdown-fm()
<autogenerated>:1 +0x20
runtime.deferreturn()
/Users/mike/.local/share/mise/installs/go/1.25.5/src/runtime/panic.go:589 +0x5c
Goroutine 57 (running) created at:
google.golang.org/grpc/internal/transport.NewHTTP2Client()
/Users/mike/go/pkg/mod/google.golang.org/grpc@v1.78.0/internal/transport/http2_client.go:467 +0x2950
google.golang.org/grpc.(*addrConn).createTransport()
/Users/mike/go/pkg/mod/google.golang.org/grpc@v1.78.0/clientconn.go:1519 +0x304
google.golang.org/grpc.(*addrConn).tryAllAddrs()
/Users/mike/go/pkg/mod/google.golang.org/grpc@v1.78.0/clientconn.go:1466 +0x404
google.golang.org/grpc.(*addrConn).resetTransportAndUnlock()
/Users/mike/go/pkg/mod/google.golang.org/grpc@v1.78.0/clientconn.go:1349 +0x178
google.golang.org/grpc.(*addrConn).connect()
/Users/mike/go/pkg/mod/google.golang.org/grpc@v1.78.0/clientconn.go:997 +0x204
google.golang.org/grpc.(*acBalancerWrapper).Connect.gowrap1()
/Users/mike/go/pkg/mod/google.golang.org/grpc@v1.78.0/balancer_wrapper.go:354 +0x34