From: Alexander Yastrebov Date: Wed, 2 Aug 2023 22:15:59 +0000 (+0000) Subject: net/http: use cancelKey to cancel request X-Git-Tag: go1.22rc1~1183 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=c7383441713da801e663e6d95cf7afb6bd500539;p=gostls13.git net/http: use cancelKey to cancel request Follows up on CL 245357 and adds missing returns in waitCondition (CL 477196) Fixes #51354 Change-Id: I7950ff889ad72c4927a969c35fedc0186e863bd6 GitHub-Last-Rev: 52ce05bc83ef88c7104df9254bc1add0dda83ae0 GitHub-Pull-Request: golang/go#61724 Reviewed-on: https://go-review.googlesource.com/c/go/+/515435 Reviewed-by: Damien Neil Reviewed-by: Bryan Mills Run-TryBot: Damien Neil Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Auto-Submit: Damien Neil --- diff --git a/src/net/http/transport.go b/src/net/http/transport.go index c07352b018..d30eb79508 100644 --- a/src/net/http/transport.go +++ b/src/net/http/transport.go @@ -2248,7 +2248,7 @@ func (pc *persistConn) readLoop() { } case <-rc.req.Cancel: alive = false - pc.t.CancelRequest(rc.req) + pc.t.cancelRequest(rc.cancelKey, errRequestCanceled) case <-rc.req.Context().Done(): alive = false pc.t.cancelRequest(rc.cancelKey, rc.req.Context().Err()) diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go index 028fecc961..bcc26aa58e 100644 --- a/src/net/http/transport_test.go +++ b/src/net/http/transport_test.go @@ -2440,6 +2440,7 @@ func testTransportCancelRequest(t *testing.T, mode testMode) { if d > 0 { t.Logf("pending requests = %d after %v (want 0)", n, d) } + return false } return true }) @@ -2599,6 +2600,65 @@ func testCancelRequestWithChannel(t *testing.T, mode testMode) { if d > 0 { t.Logf("pending requests = %d after %v (want 0)", n, d) } + return false + } + return true + }) +} + +// Issue 51354 +func TestCancelRequestWithBodyWithChannel(t *testing.T) { + run(t, testCancelRequestWithBodyWithChannel, []testMode{http1Mode}) +} +func testCancelRequestWithBodyWithChannel(t *testing.T, mode testMode) { + if testing.Short() { + t.Skip("skipping test in -short mode") + } + + const msg = "Hello" + unblockc := make(chan struct{}) + ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { + io.WriteString(w, msg) + w.(Flusher).Flush() // send headers and some body + <-unblockc + })).ts + defer close(unblockc) + + c := ts.Client() + tr := c.Transport.(*Transport) + + req, _ := NewRequest("POST", ts.URL, strings.NewReader("withbody")) + cancel := make(chan struct{}) + req.Cancel = cancel + + res, err := c.Do(req) + if err != nil { + t.Fatal(err) + } + body := make([]byte, len(msg)) + n, _ := io.ReadFull(res.Body, body) + if n != len(body) || !bytes.Equal(body, []byte(msg)) { + t.Errorf("Body = %q; want %q", body[:n], msg) + } + close(cancel) + + tail, err := io.ReadAll(res.Body) + res.Body.Close() + if err != ExportErrRequestCanceled { + t.Errorf("Body.Read error = %v; want errRequestCanceled", err) + } else if len(tail) > 0 { + t.Errorf("Spurious bytes from Body.Read: %q", tail) + } + + // Verify no outstanding requests after readLoop/writeLoop + // goroutines shut down. + waitCondition(t, 10*time.Millisecond, func(d time.Duration) bool { + n := tr.NumPendingRequestsForTesting() + if n > 0 { + if d > 0 { + t.Logf("pending requests = %d after %v (want 0)", n, d) + } + return false } return true })