- Start the server and proxy. Run the proxy with the race detector enabled:
go build -o server server.go && ./server
go build -race -o proxy proxy.go && ./proxy
- Start the client:
go build -o client && ./client
- You should see the proxy race almost immediately. See sample below.
The question is: am I doing something racy or is this a net/http bug? The race is related to how I'm timing out the requests myself -- if I remove the transport.CancelRequest
line, it doesn't seem to race. Is it the case that after cancelling the request, the transport's goroutines can still be messing with the response body?
Here is one of the race messages I get:
2013/12/20 13:24:22 Now listening on localhost:7575
==================
WARNING: DATA RACE
Read by goroutine 43:
net/http.(*body).Read()
/home/caleb/apps/go/src/pkg/net/http/transfer.go:531 +0x51
io.(*LimitedReader).Read()
/home/caleb/apps/go/src/pkg/io/io.go:398 +0x13e
io/ioutil.devNull.ReadFrom()
/home/caleb/apps/go/src/pkg/io/ioutil/ioutil.go:144 +0xbd
io.Copy()
/home/caleb/apps/go/src/pkg/io/io.go:348 +0x139
io.CopyN()
/home/caleb/apps/go/src/pkg/io/io.go:317 +0xf1
net/http.(*chunkWriter).writeHeader()
/home/caleb/apps/go/src/pkg/net/http/server.go:787 +0x1b08
net/http.(*chunkWriter).Write()
/home/caleb/apps/go/src/pkg/net/http/server.go:246 +0xb2
bufio.(*Writer).flush()
/home/caleb/apps/go/src/pkg/bufio/bufio.go:494 +0x15a
bufio.(*Writer).Flush()
/home/caleb/apps/go/src/pkg/bufio/bufio.go:483 +0x34
net/http.(*response).finishRequest()
/home/caleb/apps/go/src/pkg/net/http/server.go:999 +0x9d
net/http.(*conn).serve()
/home/caleb/apps/go/src/pkg/net/http/server.go:1171 +0xc31
Previous write by goroutine 235:
net/http.(*body).Close()
/home/caleb/apps/go/src/pkg/net/http/transfer.go:634 +0xc1
net/http.(*transferWriter).WriteBody()
/home/caleb/apps/go/src/pkg/net/http/transfer.go:207 +0x2e0
net/http.(*Request).write()
/home/caleb/apps/go/src/pkg/net/http/request.go:400 +0xa38
net/http.(*persistConn).writeLoop()
/home/caleb/apps/go/src/pkg/net/http/transport.go:797 +0x210
Goroutine 43 (running) created at:
net/http.(*Server).Serve()
/home/caleb/apps/go/src/pkg/net/http/server.go:1644 +0x2c1
net/http.(*Server).ListenAndServe()
/home/caleb/apps/go/src/pkg/net/http/server.go:1612 +0xc0
main.main()
/home/caleb/test/race-repro/proxy.go:77 +0x206
Goroutine 235 (finished) created at:
net/http.(*Transport).dialConn()
/home/caleb/apps/go/src/pkg/net/http/transport.go:529 +0x8d5
net/http.func·014()
/home/caleb/apps/go/src/pkg/net/http/transport.go:419 +0x76
==================
I noticed this bug because I was seeing this HTTP protocol error being printed by net/http:
2013/12/20 11:55:21 Unsolicited response received on idle HTTP channel starting with "H"; err=<nil>