Skip to content

Data race on EOFOnWriteFromServerToClient in forwardConnection #146

Description

@perk11

main.go:15851627

Two goroutines concurrently read/write the shared *bool
EOFOnWriteFromServerToClient (allocated via new(bool) by whichever finishes
first) with no synchronization. Both goroutines check == nil, then
assign the pointer and write through it; the final if *EOFOnWriteFromServerToClient
at line 1626 (after wg.Wait()) reads it from the parent goroutine.

  • The go test -race run passes only because in practice both copy loops
    tend to complete-and-close in a serialized way under the test workload; it is
    not guaranteed to trigger. It is a genuine data race per the Go memory model.
  • It is also pre-existing (introduced in commit 051d3048, before this
    branch), but since this branch's whole purpose is concurrency hardening it is
    worth closing now.

Fix: drop the shared-pointer pattern. wg.Wait() already happens-before
both goroutine exits, so a single bool per goroutine written before wg.Done()
and read after wg.Wait() is race-free:

var eofServerToClient bool
go func() {
    defer wg.Done()
    ... copy clientReader -> serviceConnection ...
    eofServerToClient = true   // written before wg.Done()
    serviceConnection.Close()
}()
go func() {
    defer wg.Done()
    ... copy serviceConnection -> clientConnection ...
    // eofServerToClient stays false
    clientConnection.Close()
}()
wg.Wait()
// reads after happens-before edge — safe
var reason string
if eofServerToClient { ... }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions