Skip to content

Commit 6826f5a

Browse files
committed
http2: close request bodies before RoundTrip error return
When returning an error from RoundTrip, wait for the close of the request body to complete before returning. This avoids a race between the HTTP/2 transport closing the request body and the net/http retry loop examining the readTrackingBody to see if it has been closed. For golang/go#60041 Change-Id: I8be69ff5056806406716e01e02d1f631deeca088 Reviewed-on: https://go-review.googlesource.com/c/net/+/496335 Run-TryBot: Damien Neil <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Bryan Mills <[email protected]>
1 parent ca96da6 commit 6826f5a

File tree

1 file changed

+18
-1
lines changed

1 file changed

+18
-1
lines changed

http2/transport.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1268,8 +1268,8 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
12681268

12691269
cancelRequest := func(cs *clientStream, err error) error {
12701270
cs.cc.mu.Lock()
1271-
defer cs.cc.mu.Unlock()
12721271
cs.abortStreamLocked(err)
1272+
bodyClosed := cs.reqBodyClosed
12731273
if cs.ID != 0 {
12741274
// This request may have failed because of a problem with the connection,
12751275
// or for some unrelated reason. (For example, the user might have canceled
@@ -1284,6 +1284,23 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
12841284
// will not help.
12851285
cs.cc.doNotReuse = true
12861286
}
1287+
cs.cc.mu.Unlock()
1288+
// Wait for the request body to be closed.
1289+
//
1290+
// If nothing closed the body before now, abortStreamLocked
1291+
// will have started a goroutine to close it.
1292+
//
1293+
// Closing the body before returning avoids a race condition
1294+
// with net/http checking its readTrackingBody to see if the
1295+
// body was read from or closed. See golang/go#60041.
1296+
//
1297+
// The body is closed in a separate goroutine without the
1298+
// connection mutex held, but dropping the mutex before waiting
1299+
// will keep us from holding it indefinitely if the body
1300+
// close is slow for some reason.
1301+
if bodyClosed != nil {
1302+
<-bodyClosed
1303+
}
12871304
return err
12881305
}
12891306

0 commit comments

Comments
 (0)