]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: clear reference to the request context after transport getConn
authorAlexander Yastrebov <yastrebov.alex@gmail.com>
Tue, 25 Jul 2023 10:53:58 +0000 (10:53 +0000)
committerGopher Robot <gobot@golang.org>
Mon, 21 Aug 2023 20:17:03 +0000 (20:17 +0000)
Clears wannConn ctx and prevents pending dialConnFor after connection delivered or canceled.

Updates #50798

Change-Id: I9a681ac0f222be56571fa768700220f6b5ee0888
GitHub-Last-Rev: fd6c83ab072c62d224ed8220c4c286b6e90bc151
GitHub-Pull-Request: golang/go#61524
Reviewed-on: https://go-review.googlesource.com/c/go/+/512196
Auto-Submit: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/net/http/transport.go

index d30eb79508a0cba8927276b96eb3f2afb69db870..35dfe908d825f47a302f2b92b9d25c6ad960fea4 100644 (file)
@@ -1205,7 +1205,6 @@ func (t *Transport) dial(ctx context.Context, network, addr string) (net.Conn, e
 type wantConn struct {
        cm    connectMethod
        key   connectMethodKey // cm.key()
-       ctx   context.Context  // context for dial
        ready chan struct{}    // closed when pc, err pair is delivered
 
        // hooks for testing to know when dials are done
@@ -1214,7 +1213,8 @@ type wantConn struct {
        beforeDial func()
        afterDial  func()
 
-       mu  sync.Mutex // protects pc, err, close(ready)
+       mu  sync.Mutex      // protects ctx, pc, err, close(ready)
+       ctx context.Context // context for dial, cleared after delivered or canceled
        pc  *persistConn
        err error
 }
@@ -1229,6 +1229,13 @@ func (w *wantConn) waiting() bool {
        }
 }
 
+// getCtxForDial returns context for dial or nil if connection was delivered or canceled.
+func (w *wantConn) getCtxForDial() context.Context {
+       w.mu.Lock()
+       defer w.mu.Unlock()
+       return w.ctx
+}
+
 // tryDeliver attempts to deliver pc, err to w and reports whether it succeeded.
 func (w *wantConn) tryDeliver(pc *persistConn, err error) bool {
        w.mu.Lock()
@@ -1238,6 +1245,7 @@ func (w *wantConn) tryDeliver(pc *persistConn, err error) bool {
                return false
        }
 
+       w.ctx = nil
        w.pc = pc
        w.err = err
        if w.pc == nil && w.err == nil {
@@ -1255,6 +1263,7 @@ func (w *wantConn) cancel(t *Transport, err error) {
                close(w.ready) // catch misbehavior in future delivery
        }
        pc := w.pc
+       w.ctx = nil
        w.pc = nil
        w.err = err
        w.mu.Unlock()
@@ -1463,8 +1472,12 @@ func (t *Transport) queueForDial(w *wantConn) {
 // If the dial is canceled or unsuccessful, dialConnFor decrements t.connCount[w.cm.key()].
 func (t *Transport) dialConnFor(w *wantConn) {
        defer w.afterDial()
+       ctx := w.getCtxForDial()
+       if ctx == nil {
+               return
+       }
 
-       pc, err := t.dialConn(w.ctx, w.cm)
+       pc, err := t.dialConn(ctx, w.cm)
        delivered := w.tryDeliver(pc, err)
        if err == nil && (!delivered || pc.alt != nil) {
                // pconn was not passed to w,