Skip to content

net/http: data race in TestTransportResponseHeaderTimeout #7264

Closed
@dvyukov

Description

@dvyukov
parent: 19010:d067c6de4ec3 tip, linux/amd64
$ go test -v -race -cpu=16,16,16,16 -run=TestTransportResponseHeaderTimeout net/http

WARNING: DATA RACE
Write by goroutine 51:
  sync.raceWrite()
      src/pkg/sync/race.go:41 +0x35
  sync.(*WaitGroup).Wait()
      src/pkg/sync/waitgroup.go:120 +0x16d
  net/http/httptest.(*Server).Close()
      src/pkg/net/http/httptest/server.go:168 +0x6a
  net/http_test.TestTransportResponseHeaderTimeout()
      src/pkg/net/http/transport_test.go:1254 +0x6de
  testing.tRunner()
      src/pkg/testing/testing.go:398 +0x10f

Previous read by goroutine 366:
  sync.raceRead()
      src/pkg/sync/race.go:37 +0x35
  sync.(*WaitGroup).Add()
      src/pkg/sync/waitgroup.go:60 +0xc1
  net/http/httptest.(*waitGroupHandler).ServeHTTP()
      src/pkg/net/http/httptest/server.go:198 +0x5e
  net/http.serverHandler.ServeHTTP()
      src/pkg/net/http/server.go:1599 +0x1cc
  net/http.(*conn).serve()
      src/pkg/net/http/server.go:1162 +0xc36

Goroutine 51 (running) created at:
  testing.RunTests()
      src/pkg/testing/testing.go:479 +0xbb5
  testing.Main()
      src/pkg/testing/testing.go:411 +0xad
  main.main()
      /tmp/go-build864201384/net/http/_test/_testmain.go:443 +0xdc

Goroutine 366 (running) created at:
  net/http.(*Server).Serve()
      src/pkg/net/http/server.go:1646 +0x2d1


The test sends request to /slow:
    mux.HandleFunc("/slow", func(w ResponseWriter, r *Request) { time.Sleep(2 * time.Second) })
gets timeout error after 500ms and then closes the server with:
    defer ts.Close()

Close waits for all outstanding handlers to finish:
func (s *Server) Close() {
    s.Listener.Close()
    s.wg.Wait()
    ...
}

The wg is +1'ed in the handler:
func (h *waitGroupHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    h.s.wg.Add(1)
    defer h.s.wg.Done() // a defer, in case ServeHTTP below panics
    h.h.ServeHTTP(w, r)
}

So essentially when the test closes the server and waits for all outstanding handlers to
finish, ServeHTTP may not yet have +1'ed wg, so wg.Wait will return early w/o waiting
for the handler.


httptest.NewServer API assumes that tests wait at least for handlers to start executing.
Then Close will wait for handlers to finish.

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeTestingAn issue that has been verified to require only test changes, not just a test failure.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions