@@ -6969,3 +6969,65 @@ func testProxyAuthHeader(t *testing.T, mode testMode) {
6969
6969
}
6970
6970
resp .Body .Close ()
6971
6971
}
6972
+
6973
+ // Issue 61708
6974
+ func TestTransportReqCancelerCleanupOnRequestBodyWriteError (t * testing.T ) {
6975
+ ln := newLocalListener (t )
6976
+ addr := ln .Addr ().String ()
6977
+
6978
+ done := make (chan struct {})
6979
+ go func () {
6980
+ conn , err := ln .Accept ()
6981
+ if err != nil {
6982
+ t .Errorf ("ln.Accept: %v" , err )
6983
+ return
6984
+ }
6985
+ // Start reading request before sending response to avoid
6986
+ // "Unsolicited response received on idle HTTP channel" RoundTrip error.
6987
+ if _ , err := io .ReadFull (conn , make ([]byte , 1 )); err != nil {
6988
+ t .Errorf ("conn.Read: %v" , err )
6989
+ return
6990
+ }
6991
+ io .WriteString (conn , "HTTP/1.1 200\r \n Content-Length: 3\r \n \r \n foo" )
6992
+ <- done
6993
+ conn .Close ()
6994
+ }()
6995
+
6996
+ didRead := make (chan bool )
6997
+ SetReadLoopBeforeNextReadHook (func () { didRead <- true })
6998
+ defer SetReadLoopBeforeNextReadHook (nil )
6999
+
7000
+ tr := & Transport {}
7001
+
7002
+ // Send a request with a body guaranteed to fail on write.
7003
+ req , err := NewRequest ("POST" , "http://" + addr , io .LimitReader (neverEnding ('x' ), 1 << 30 ))
7004
+ if err != nil {
7005
+ t .Fatalf ("NewRequest: %v" , err )
7006
+ }
7007
+
7008
+ resp , err := tr .RoundTrip (req )
7009
+ if err != nil {
7010
+ t .Fatalf ("tr.RoundTrip: %v" , err )
7011
+ }
7012
+
7013
+ close (done )
7014
+
7015
+ // Before closing response body wait for readLoopDone goroutine
7016
+ // to complete due to closed connection by writeLoop.
7017
+ <- didRead
7018
+
7019
+ resp .Body .Close ()
7020
+
7021
+ // Verify no outstanding requests after readLoop/writeLoop
7022
+ // goroutines shut down.
7023
+ waitCondition (t , 10 * time .Millisecond , func (d time.Duration ) bool {
7024
+ n := tr .NumPendingRequestsForTesting ()
7025
+ if n > 0 {
7026
+ if d > 0 {
7027
+ t .Logf ("pending requests = %d after %v (want 0)" , n , d )
7028
+ }
7029
+ return false
7030
+ }
7031
+ return true
7032
+ })
7033
+ }
0 commit comments