}
var DefaultUserAgent = defaultUserAgent
+
+// SetPendingDialHooks sets the hooks that run before and after handling
+// pending dials.
+func SetPendingDialHooks(before, after func()) {
+ prePendingDial, postPendingDial = before, after
+}
return net.Dial(network, addr)
}
+// Testing hooks:
+var prePendingDial, postPendingDial func()
+
// getConn dials and creates a new persistConn to the target as
// specified in the connectMethod. This includes doing a proxy CONNECT
// and/or setting up TLS. If this doesn't return an error, the persistConn
dialc := make(chan dialRes)
handlePendingDial := func() {
- if v := <-dialc; v.err == nil {
- t.putIdleConn(v.pc)
+ if prePendingDial != nil {
+ prePendingDial()
}
+ go func() {
+ if v := <-dialc; v.err == nil {
+ t.putIdleConn(v.pc)
+ }
+ if postPendingDial != nil {
+ postPendingDial()
+ }
+ }()
}
cancelc := make(chan struct{})
// else's dial that they didn't use.
// But our dial is still going, so give it away
// when it finishes:
- go handlePendingDial()
+ handlePendingDial()
return pc, nil
case <-cancelc:
- go handlePendingDial()
+ handlePendingDial()
return nil, errors.New("net/http: request canceled while waiting for connection")
}
}
var wg sync.WaitGroup
wg.Add(numReqs)
- tr := &Transport{
- Dial: func(netw, addr string) (c net.Conn, err error) {
- // Due to the Transport's "socket late
- // binding" (see idleConnCh in transport.go),
- // the numReqs HTTP requests below can finish
- // with a dial still outstanding. So count
- // our dials as work too so the leak checker
- // doesn't complain at us.
- wg.Add(1)
- defer wg.Done()
- return net.Dial(netw, addr)
- },
- }
+ // Due to the Transport's "socket late binding" (see
+ // idleConnCh in transport.go), the numReqs HTTP requests
+ // below can finish with a dial still outstanding. To keep
+ // the leak checker happy, keep track of pending dials and
+ // wait for them to finish (and be closed or returned to the
+ // idle pool) before we close idle connections.
+ SetPendingDialHooks(func() { wg.Add(1) }, wg.Done)
+ defer SetPendingDialHooks(nil, nil)
+
+ tr := &Transport{}
defer tr.CloseIdleConnections()
+
c := &Client{Transport: tr}
reqs := make(chan string)
defer close(reqs)