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.
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) {
}
func (r *readTrackingBody) Close() error {
- r.didClose = true
+ if !r.didClose.CompareAndSwap(false, true) {
+ return nil
+ }
return r.ReadCloser.Close()
}
// 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 {