Skip to content

Commit 182336b

Browse files
bradfitzneild
authored andcommitted
net/http: fix data race in client
Fixes golang#73522 Co-authored-by: Damien Neil <[email protected]> Change-Id: I6fb408a0b03bc387f443e17e6f9d0bac32eff31e Reviewed-on: https://go-review.googlesource.com/c/go/+/694815 LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Damien Neil <[email protected]> Reviewed-by: Damien Neil <[email protected]> Reviewed-by: David Chase <[email protected]>
1 parent f04421e commit 182336b

File tree

1 file changed

+8
-6
lines changed

1 file changed

+8
-6
lines changed

src/net/http/transport.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ func (t *Transport) roundTrip(req *Request) (_ *Response, err error) {
722722
if e, ok := err.(transportReadFromServerError); ok {
723723
err = e.err
724724
}
725-
if b, ok := req.Body.(*readTrackingBody); ok && !b.didClose {
725+
if b, ok := req.Body.(*readTrackingBody); ok && !b.didClose.Load() {
726726
// Issue 49621: Close the request body if pconn.roundTrip
727727
// didn't do so already. This can happen if the pconn
728728
// write loop exits without reading the write request.
@@ -752,8 +752,8 @@ var errCannotRewind = errors.New("net/http: cannot rewind body after connection
752752

753753
type readTrackingBody struct {
754754
io.ReadCloser
755-
didRead bool
756-
didClose bool
755+
didRead bool // not atomic.Bool because only one goroutine (the user's) should be accessing
756+
didClose atomic.Bool
757757
}
758758

759759
func (r *readTrackingBody) Read(data []byte) (int, error) {
@@ -762,7 +762,9 @@ func (r *readTrackingBody) Read(data []byte) (int, error) {
762762
}
763763

764764
func (r *readTrackingBody) Close() error {
765-
r.didClose = true
765+
if !r.didClose.CompareAndSwap(false, true) {
766+
return nil
767+
}
766768
return r.ReadCloser.Close()
767769
}
768770

@@ -784,10 +786,10 @@ func setupRewindBody(req *Request) *Request {
784786
// rewindBody takes care of closing req.Body when appropriate
785787
// (in all cases except when rewindBody returns req unmodified).
786788
func rewindBody(req *Request) (rewound *Request, err error) {
787-
if req.Body == nil || req.Body == NoBody || (!req.Body.(*readTrackingBody).didRead && !req.Body.(*readTrackingBody).didClose) {
789+
if req.Body == nil || req.Body == NoBody || (!req.Body.(*readTrackingBody).didRead && !req.Body.(*readTrackingBody).didClose.Load()) {
788790
return req, nil // nothing to rewind
789791
}
790-
if !req.Body.(*readTrackingBody).didClose {
792+
if !req.Body.(*readTrackingBody).didClose.Load() {
791793
req.closeBody()
792794
}
793795
if req.GetBody == nil {

0 commit comments

Comments
 (0)