Closed
Description
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.