diff options
author | Brad Fitzpatrick <bradfitz@golang.org> | 2012-02-14 12:48:56 +1100 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@golang.org> | 2012-02-14 12:48:56 +1100 |
commit | b3b43752b70fcb5e97361a810315469c65becfd6 (patch) | |
tree | f14174d874516abcce051251e2219792cc97ac38 /src/pkg/net/http/transport.go | |
parent | 6dd31594b8bd0b82a65ec7e2ef5095ab897c7ae8 (diff) | |
download | go-b3b43752b70fcb5e97361a810315469c65becfd6.tar.gz |
net/http: fix client goroutine leak with persistent connections
Thanks to Sascha Matzke & Florian Weimer for diagnosing.
R=golang-dev, adg, bradfitz, kevlar
CC=golang-dev
http://codereview.appspot.com/5656046
Diffstat (limited to 'src/pkg/net/http/transport.go')
-rw-r--r-- | src/pkg/net/http/transport.go | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/src/pkg/net/http/transport.go b/src/pkg/net/http/transport.go index 510e55b05..3e48abafb 100644 --- a/src/pkg/net/http/transport.go +++ b/src/pkg/net/http/transport.go @@ -235,15 +235,19 @@ func (cm *connectMethod) proxyAuth() string { return "" } -func (t *Transport) putIdleConn(pconn *persistConn) { +// putIdleConn adds pconn to the list of idle persistent connections awaiting +// a new request. +// If pconn is no longer needed or not in a good state, putIdleConn +// returns false. +func (t *Transport) putIdleConn(pconn *persistConn) bool { t.lk.Lock() defer t.lk.Unlock() if t.DisableKeepAlives || t.MaxIdleConnsPerHost < 0 { pconn.close() - return + return false } if pconn.isBroken() { - return + return false } key := pconn.cacheKey max := t.MaxIdleConnsPerHost @@ -252,9 +256,10 @@ func (t *Transport) putIdleConn(pconn *persistConn) { } if len(t.idleConn[key]) >= max { pconn.close() - return + return false } t.idleConn[key] = append(t.idleConn[key], pconn) + return true } func (t *Transport) getIdleConn(cm *connectMethod) (pconn *persistConn) { @@ -565,7 +570,9 @@ func (pc *persistConn) readLoop() { lastbody = resp.Body waitForBodyRead = make(chan bool) resp.Body.(*bodyEOFSignal).fn = func() { - pc.t.putIdleConn(pc) + if !pc.t.putIdleConn(pc) { + alive = false + } waitForBodyRead <- true } } else { @@ -578,7 +585,9 @@ func (pc *persistConn) readLoop() { // read it (even though it'll just be 0, EOF). lastbody = nil - pc.t.putIdleConn(pc) + if !pc.t.putIdleConn(pc) { + alive = false + } } } |