From d3b9193c8d2cf29b135910b0990490d42c86b95f Mon Sep 17 00:00:00 2001 From: Matthew Jaffee Date: Mon, 20 Dec 2021 21:48:45 -0600 Subject: [PATCH] try to fix data race with http lib WARNING: DATA RACE Write at 0x00c008121e80 by goroutine 235: bytes.(*Reader).WriteTo() /usr/local/go/src/bytes/reader.go:139 +0x45 github.com/molecula/featurebase/v2/http.nopCloser.WriteTo() :1 +0x5d io.copyBuffer() /usr/local/go/src/io/io.go:391 +0x482 io.Copy() /usr/local/go/src/io/io.go:368 +0x78 net/http.(*transferWriter).doBodyCopy() /usr/local/go/src/net/http/transfer.go:400 +0x2f net/http.(*transferWriter).writeBody() /usr/local/go/src/net/http/transfer.go:364 +0xc9a net/http.(*Request).write() /usr/local/go/src/net/http/request.go:682 +0x887 net/http.(*persistConn).writeLoop() /usr/local/go/src/net/http/transport.go:2343 +0x349 Previous write at 0x00c008121e80 by goroutine 192: bytes.(*Reader).Seek() /usr/local/go/src/bytes/reader.go:118 +0x824 github.com/molecula/featurebase/v2/http.(*InternalClient).doWithRetry() /go/src/github.com/molecula/featurebase/http/client.go:1773 +0x86d github.com/molecula/featurebase/v2/http.(*InternalClient).executeRequest() /go/src/github.com/molecula/featurebase/http/client.go:1806 +0x15b github.com/molecula/featurebase/v2/http.(*InternalClient).CreateIndex() /go/src/github.com/molecula/featurebase/http/client.go:433 +0xbf8 github.com/molecula/featurebase/v2/server_test.TestMain_Set_Quick.func1() /go/src/github.com/molecula/featurebase/server/server_test.go:64 +0x624 testing.tRunner() /usr/local/go/src/testing/testing.go:1123 +0x202 Goroutine 235 (running) created at: net/http.(*Transport).dialConn() /usr/local/go/src/net/http/transport.go:1709 +0xc30 net/http.(*Transport).dialConnFor() /usr/local/go/src/net/http/transport.go:1421 +0x151 Goroutine 192 (running) created at: testing.(*T).Run() /usr/local/go/src/testing/testing.go:1168 +0x5bb github.com/molecula/featurebase/v2/server_test.TestMain_Set_Quick() /go/src/github.com/molecula/featurebase/server/server_test.go:45 +0x116 testing.tRunner() /usr/local/go/src/testing/testing.go:1123 +0x202 --- http/client.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/http/client.go b/http/client.go index 0e2b1b428..c32dd86ae 100644 --- a/http/client.go +++ b/http/client.go @@ -1755,22 +1755,22 @@ func (n nopCloser) Close() error { func (c *InternalClient) doWithRetry(req *http.Request) (*http.Response, error) { sleepDuration := time.Second - newBody := nopCloser{} + var bod []byte + var err error if req.Body != nil { - bod, err := ioutil.ReadAll(req.Body) + bod, err = ioutil.ReadAll(req.Body) if err != nil { return nil, errors.Wrap(err, "reading body") } - newBody.Reader = bytes.NewReader(bod) - req.Body = newBody + req.Body = nopCloser{bytes.NewReader(bod)} } resp, err := c.httpClient.Do(req) // start timer after first request, so if retryPeriod > 0 we // pretty much always do at least one retry start := time.Now() for ; err != nil || resp.StatusCode < 200 || resp.StatusCode >= 300; resp, err = c.httpClient.Do(req) { - if newBody.Reader != nil { - newBody.Seek(0, io.SeekStart) + if req.Body != nil { + req.Body = nopCloser{bytes.NewReader(bod)} // can't seek due to races with http lib internals } if time.Since(start) > c.retryPeriod { break