Open bcmills opened 4 years ago
Change https://golang.org/cl/227924 mentions this issue: net/http/httptest: add a regression test for #38370
See previously #12262.
Curiously, I'm not able to get the test to fail without the race detector.
I suspect that httptest
may actually be synchronizing itself via the network socket in a way that is hidden from the race detector.
@bcmills Could this be related to the same issue as #36946? Looks like the httptest server's Close
method calls SetKeepAlivesEnabled(false)
:
https://golang.org/src/net/http/httptest/server.go?s=5496:5520#L190
I believe that might explain why the test server is not waiting for the handler to complete when HTTP/2 is enabled.
Too late for 1.15, and not entirely clear that there is a real problem. Moving to Backlog.
All races observed since the last comment are attributable to either #45237 or #49850 (which may actually be a variant of the same issue). This may have been resolved by some intervening change (to one or more of net/http
, the runtime, and/or the race detector).
greplogs --dashboard -md -l -e '^WARNING: DATA RACE\n.+ by goroutine \d+:\n(?: .+\n \s+.+\n)* net/http/httptest' --since=2020-06-26
2021-11-29T02:12:23-d83791d-f6103e9/linux-amd64-race 2021-04-12T21:25:46-afb366f-f12cf76/windows-amd64-race 2021-03-31T16:59:18-cb1fcc7-887c0d8/freebsd-amd64-race 2021-03-23T23:09:33-08027d5-87a3ac5/windows-amd64-race 2021-02-24T04:11:43-9060382-6ba4a30/linux-amd64-race 2020-12-23T17:01:35-986b41b-49d0b23/freebsd-amd64-race 2020-12-21T21:48:47-986b41b-bc7e4d9/freebsd-amd64-race 2020-10-26T18:10:12-146b70c-c5dea8f/freebsd-amd64-race 2020-10-19T12:40:52-7b1cca2-53094ac/windows-amd64-race 2020-09-29T22:49:58-5d4f700-0e85fd7/windows-amd64-race 2020-09-28T22:28:06-5d4f700-1f4d035/freebsd-amd64-race 2020-08-21T23:45:40-3edf25e-f454f70/freebsd-amd64-race 2020-08-12T23:16:53-ab34263-50f63a7/freebsd-amd64-race
Oh, neat! The regression test in https://go.dev/cl/227924 actually still fails.
(attn @neild)
Interesting! The race that is now reported is entirely on the client side. 🤔
Ah, that race is #60041.
httptest
doesn't do anything to wait for handlers to exit.
httptest.Server.Close
closes the connection listener and waits for http.Server.Serve
to return, but Serve
doesn't wait for handler goroutines to complete before returning.
In fact, I don't think there's anything in net/http
which is documented as waiting for handler goroutines to complete. Server.Shutdown
waits "for connections to return to idle", but a handler that's still running for a request on a now-closed connection won't block Shutdown
.
httptest.Server.Close
"blocks until all outstanding requests on this server have completed", but that's a bit ambiguous on whether it blocks until handlers have returned.
This doesn't look like a race condition; there just isn't anything that waits for handlers to exit. Perhaps there should be.
Per https://pkg.go.dev/net/http#Handler:
Returning signals that the request is finished
To me, that makes the phrase “blocks until all outstanding requests on this server have completed” completely unambiguous: a (server-side) request is not “completed” until its handler has returned.
Change https://go.dev/cl/539436 mentions this issue: net/http: remove arbitrary timeouts in tests of Server.ErrorLog
While investigating #37669, I saw a reported race that led me to believe that, contrary to its documentation,
(*httptest.Server).Close
was not blocking for requests to complete.To check that hypothesis, I added the following test function:
It reliably fails under the race detector with even a very modest count, indicating that the server is not waiting for the handler to complete when HTTP/2 is enabled:
CC @bradfitz @tombergan @nerd2