mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
net/http: fix data race in client
Fixes #73522 Co-authored-by: Damien Neil <dneil@google.com> Change-Id: I6fb408a0b03bc387f443e17e6f9d0bac32eff31e Reviewed-on: https://go-review.googlesource.com/c/go/+/694815 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Damien Neil <dneil@google.com> Reviewed-by: Damien Neil <dneil@google.com> Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
f04421ea9a
commit
182336bf05
1 changed files with 8 additions and 6 deletions
|
|
@ -722,7 +722,7 @@ func (t *Transport) roundTrip(req *Request) (_ *Response, err error) {
|
|||
if e, ok := err.(transportReadFromServerError); ok {
|
||||
err = e.err
|
||||
}
|
||||
if b, ok := req.Body.(*readTrackingBody); ok && !b.didClose {
|
||||
if b, ok := req.Body.(*readTrackingBody); ok && !b.didClose.Load() {
|
||||
// Issue 49621: Close the request body if pconn.roundTrip
|
||||
// didn't do so already. This can happen if the pconn
|
||||
// write loop exits without reading the write request.
|
||||
|
|
@ -752,8 +752,8 @@ var errCannotRewind = errors.New("net/http: cannot rewind body after connection
|
|||
|
||||
type readTrackingBody struct {
|
||||
io.ReadCloser
|
||||
didRead bool
|
||||
didClose bool
|
||||
didRead bool // not atomic.Bool because only one goroutine (the user's) should be accessing
|
||||
didClose atomic.Bool
|
||||
}
|
||||
|
||||
func (r *readTrackingBody) Read(data []byte) (int, error) {
|
||||
|
|
@ -762,7 +762,9 @@ func (r *readTrackingBody) Read(data []byte) (int, error) {
|
|||
}
|
||||
|
||||
func (r *readTrackingBody) Close() error {
|
||||
r.didClose = true
|
||||
if !r.didClose.CompareAndSwap(false, true) {
|
||||
return nil
|
||||
}
|
||||
return r.ReadCloser.Close()
|
||||
}
|
||||
|
||||
|
|
@ -784,10 +786,10 @@ func setupRewindBody(req *Request) *Request {
|
|||
// rewindBody takes care of closing req.Body when appropriate
|
||||
// (in all cases except when rewindBody returns req unmodified).
|
||||
func rewindBody(req *Request) (rewound *Request, err error) {
|
||||
if req.Body == nil || req.Body == NoBody || (!req.Body.(*readTrackingBody).didRead && !req.Body.(*readTrackingBody).didClose) {
|
||||
if req.Body == nil || req.Body == NoBody || (!req.Body.(*readTrackingBody).didRead && !req.Body.(*readTrackingBody).didClose.Load()) {
|
||||
return req, nil // nothing to rewind
|
||||
}
|
||||
if !req.Body.(*readTrackingBody).didClose {
|
||||
if !req.Body.(*readTrackingBody).didClose.Load() {
|
||||
req.closeBody()
|
||||
}
|
||||
if req.GetBody == nil {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue