Revert "net/http: fix data race due to writeLoop goroutine left running"
This reverts CL 232799.
Reason for revert: net/http test is failing on all longtest builders.
Change-Id: I4694e34f35419bab2d0b45fa6d8c3ac2aa1f51a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/250597
Run-TryBot: Bryan C. Mills <bcmills@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/net/http/transport.go b/src/net/http/transport.go
index 05ff3ba..d37b52b 100644
--- a/src/net/http/transport.go
+++ b/src/net/http/transport.go
@@ -1963,15 +1963,6 @@
return nil
}
- // Wait for the writeLoop goroutine to terminate to avoid data
- // races on callers who mutate the request on failure.
- //
- // When resc in pc.roundTrip and hence rc.ch receives a responseAndError
- // with a non-nil error it implies that the persistConn is either closed
- // or closing. Waiting on pc.writeLoopDone is hence safe as all callers
- // close closech which in turn ensures writeLoop returns.
- <-pc.writeLoopDone
-
// If the request was canceled, that's better than network
// failures that were likely the result of tearing down the
// connection.
@@ -1997,6 +1988,7 @@
return err
}
if pc.isBroken() {
+ <-pc.writeLoopDone
if pc.nwrite == startBytesWritten {
return nothingWrittenError{err}
}
diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
index 29d1ec3..2d9ca10 100644
--- a/src/net/http/transport_test.go
+++ b/src/net/http/transport_test.go
@@ -25,7 +25,6 @@
"io"
"io/ioutil"
"log"
- mrand "math/rand"
"net"
. "net/http"
"net/http/httptest"
@@ -6285,94 +6284,3 @@
t.Fatalf("Error mismatch\nGot: %q\nWanted substring: %q", got, want)
}
}
-
-// dumpConn is a net.Conn which writes to Writer and reads from Reader
-type dumpConn struct {
- io.Writer
- io.Reader
-}
-
-func (c *dumpConn) Close() error { return nil }
-func (c *dumpConn) LocalAddr() net.Addr { return nil }
-func (c *dumpConn) RemoteAddr() net.Addr { return nil }
-func (c *dumpConn) SetDeadline(t time.Time) error { return nil }
-func (c *dumpConn) SetReadDeadline(t time.Time) error { return nil }
-func (c *dumpConn) SetWriteDeadline(t time.Time) error { return nil }
-
-// delegateReader is a reader that delegates to another reader,
-// once it arrives on a channel.
-type delegateReader struct {
- c chan io.Reader
- r io.Reader // nil until received from c
-}
-
-func (r *delegateReader) Read(p []byte) (int, error) {
- if r.r == nil {
- r.r = <-r.c
- }
- return r.r.Read(p)
-}
-
-func testTransportRace(req *Request) {
- save := req.Body
- pr, pw := io.Pipe()
- defer pr.Close()
- defer pw.Close()
- dr := &delegateReader{c: make(chan io.Reader)}
-
- t := &Transport{
- Dial: func(net, addr string) (net.Conn, error) {
- return &dumpConn{pw, dr}, nil
- },
- }
- defer t.CloseIdleConnections()
-
- quitReadCh := make(chan struct{})
- // Wait for the request before replying with a dummy response:
- go func() {
- defer close(quitReadCh)
-
- req, err := ReadRequest(bufio.NewReader(pr))
- if err == nil {
- // Ensure all the body is read; otherwise
- // we'll get a partial dump.
- io.Copy(ioutil.Discard, req.Body)
- req.Body.Close()
- }
- select {
- case dr.c <- strings.NewReader("HTTP/1.1 204 No Content\r\nConnection: close\r\n\r\n"):
- case quitReadCh <- struct{}{}:
- }
- }()
-
- t.RoundTrip(req)
-
- // Ensure the reader returns before we reset req.Body to prevent
- // a data race on req.Body.
- pw.Close()
- <-quitReadCh
-
- req.Body = save
-}
-
-// Issue 37669
-// Test that a cancellation doesn't result in a data race due to the writeLoop
-// goroutine being left running, if the caller mutates the processed Request
-// upon completion.
-func TestErrorWriteLoopRace(t *testing.T) {
- for i := 0; i < 1000; i++ {
- ctx, cancel := context.WithCancel(context.Background())
- r := bytes.NewBuffer(make([]byte, 10000))
- delay := time.Duration(mrand.Intn(5)) * time.Millisecond
- go func() {
- time.Sleep(delay)
- cancel()
- }()
- req, err := NewRequestWithContext(ctx, MethodPost, "http://example.com", r)
- if err != nil {
- t.Fatal(err)
- }
-
- testTransportRace(req)
- }
-}