net/http: data race in http/2 server #20704
Closed
Comments
Simplified reproduction. Race is triggered on the first run for me. package main
import (
"crypto/tls"
"net/http"
"net/http/httptest"
"golang.org/x/net/http2"
)
const (
itemSize = 1 << 10
itemCount = 100
)
func main() {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
for i := 0; i < itemCount; i++ {
_, err := w.Write(make([]byte, itemSize))
if err != nil {
return
}
}
})
srv := httptest.NewUnstartedServer(handler)
srv.TLS = &tls.Config{
NextProtos: []string{"h2"},
}
srv.StartTLS()
cl := &http.Client{
Transport: &http2.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
}
for i := 0; i < 10000; i++ {
resp, err := cl.Get(srv.URL)
if err != nil {
panic(err)
}
resp.Body.Close()
}
} |
/cc @tombergan |
CL https://golang.org/cl/46008 mentions this issue. |
gopherbot
pushed a commit
to golang/net
that referenced
this issue
Jun 19, 2017
With Tom Bergan. Updates golang/go#20704 Change-Id: Ib71202801f8c72af2f22865899c93df1f3753fdd Reviewed-on: https://go-review.googlesource.com/46008 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Tom Bergan <tombergan@google.com>
CL https://golang.org/cl/46093 mentions this issue. |
c3mb0
pushed a commit
to c3mb0/net
that referenced
this issue
Apr 2, 2018
With Tom Bergan. Updates golang/go#20704 Change-Id: Ib71202801f8c72af2f22865899c93df1f3753fdd Reviewed-on: https://go-review.googlesource.com/46008 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Tom Bergan <tombergan@google.com>
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
It looks like the race is on the
net/http.(*http2responseWriterState).bw
field, which survives while the *http2responseWriterState value is passed through a sync.Pool. The goroutine running the handler does a write on that bufio.Writer, while another goroutine reads from it as part of an asynchronous frame write.http2responseWriter.handlerDone puts rws into the pool, but does not appear to check if there's an async write occurring.
What version of Go are you using (
go version
)?What operating system and processor architecture are you using (
go env
)?What did you do?
I ran the following program with the race detector: https://play.golang.org/p/Q9uoDKSNpf
What did you expect to see?
I expected no data races to be detected.
What did you see instead?
With both go1.8.3 and go1.9beta1, the race detector finds data races within net/http's HTTP/2 code (bundled from x/net/http2).
With
go1.8 build -gcflags="-trimpath=$PWD" -i -race -o /tmp/h2_race . && stress -p=1 /tmp/h2_race
, the race detector finds data races in about 1 in 5 runs of the program. Here's one from go1.8.3:And an example of the problem in go1.9beta1:
The text was updated successfully, but these errors were encountered: