Closed
Description
Please refer to this gist: https://gist.github.com/cespare/f4352a11bac5cced9458 (I have also attached these files in a tarball to this issue.) In particular, note the proxy handler: https://gist.github.com/cespare/f4352a11bac5cced9458#file-proxy-go-L34-L67 I have an HTTP reverse proxy similar to httputil.ReverseProxy. At high loads, I noticed a few protocol errors like this: "2013/12/20 11:55:21 Unsolicited response received on idle HTTP channel starting with "H"; err=<nil>" When I enabled the race detector, it found a race (pasted at the bottom of the bug report.) The race is between http client code (one of Transport's goroutines) and a server goroutine. Repro steps: 1. Run the server: go build -o server server.go && ./server 2. Run the proxy with the race detector: go build -race -o proxy proxy.go && ./proxy 3. Run the client to make a bunch of requests to the proxy: go build -o client client.go && ./client What is the expected output? No races What do you see instead? I immediately get data race warnings. Which compiler are you using (5g, 6g, 8g, gccgo)? 6g Which operating system are you using? linux/amd64 Which version are you using? (run 'go version') 1.2 Also tested and confirmed in: 1.1, 1.1.1, 1.1.2, and devel +a768c0592b88 Notes and questions: - This is a much-reduced version of my real application - The error repros reliably only with higher numbers of concurrent connections - I can only get the race warning to trigger by using GOMAXPROCS > 1 - The triggering condition seems to be that I'm canceling requests myself, after some timeout, by calling Transport.CancelRequest (in this minimal version I could just rely on ResponseHeaderTimeout, but in my real application I need per-request timeouts) - Removing transport.CancelRequest gets rid of the race warnings. Similarly, I cannot repro by using httputil.ReverseProxy. - Is my usage of RoundTrip in conjunction with CancelRequest ok? I am assuming that after RoundTrip returns, you need to handle it the usual way (close the body if err == nil) even if you had called CancelRequest previously. Here's the race: 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 ==================
Attachments:
- cespare-race-repro.tgz (3200 bytes)
Metadata
Metadata
Assignees
Type
Projects
Relationships
Development
No branches or pull requests
Activity
cespare commentedon Dec 20, 2013
Comment 1:
dvyukov commentedon Dec 21, 2013
Comment 2:
Labels changed: added threadsanitizer.
cespare commentedon Dec 23, 2013
Comment 3:
davecheney commentedon Dec 27, 2013
Comment 4:
Labels changed: added release-go1.3, repo-main.
Owner changed to @davecheney.
Status changed to Accepted.
dvyukov commentedon Dec 27, 2013
Comment 5:
cespare commentedon Dec 27, 2013
Comment 6:
cespare commentedon Dec 27, 2013
Comment 7:
cespare commentedon Dec 27, 2013
Comment 8:
davecheney commentedon Dec 27, 2013
Comment 9:
davecheney commentedon Dec 27, 2013
Comment 10:
davecheney commentedon Dec 27, 2013
Comment 11:
cespare commentedon Dec 27, 2013
Comment 12:
cespare commentedon Dec 27, 2013
Comment 13:
davecheney commentedon Dec 27, 2013
Comment 14:
cespare commentedon Dec 27, 2013
Comment 15:
1 remaining item
cespare commentedon Dec 31, 2013
Comment 17:
bradfitz commentedon Jan 6, 2014
Comment 18:
bradfitz commentedon Jan 7, 2014
Comment 19:
bradfitz commentedon Jan 7, 2014
Comment 20:
This issue was closed by revision affab3f.
Status changed to Fixed.
bradfitz commentedon Jan 14, 2014
Comment 21:
This issue was updated by revision 9b0560e.
bradfitz commentedon Mar 24, 2014
Comment 22:
Issue #7595 has been merged into this issue.