Commit d645adc3 authored by Yoshiyuki Kanno's avatar Yoshiyuki Kanno Committed by Brad Fitzpatrick

net/http: fix Transport deadlock

This patch intend to fix following issues.
http://code.google.com/p/go/issues/detail?id=2616

Fixes #2616.

R=golang-dev, bradfitz, nekotaroh
CC=golang-dev
https://golang.org/cl/5532057
parent ee9bfb02
...@@ -494,12 +494,6 @@ func (pc *persistConn) isBroken() bool { ...@@ -494,12 +494,6 @@ func (pc *persistConn) isBroken() bool {
return pc.broken return pc.broken
} }
func (pc *persistConn) expectingResponse() bool {
pc.lk.Lock()
defer pc.lk.Unlock()
return pc.numExpectedResponses > 0
}
var remoteSideClosedFunc func(error) bool // or nil to use default var remoteSideClosedFunc func(error) bool // or nil to use default
func remoteSideClosed(err error) bool { func remoteSideClosed(err error) bool {
...@@ -518,14 +512,18 @@ func (pc *persistConn) readLoop() { ...@@ -518,14 +512,18 @@ func (pc *persistConn) readLoop() {
for alive { for alive {
pb, err := pc.br.Peek(1) pb, err := pc.br.Peek(1)
if !pc.expectingResponse() {
pc.lk.Lock()
if pc.numExpectedResponses == 0 {
pc.closeLocked()
pc.lk.Unlock()
if len(pb) > 0 { if len(pb) > 0 {
log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v", log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v",
string(pb), err) string(pb), err)
} }
pc.close()
return return
} }
pc.lk.Unlock()
rc := <-pc.reqch rc := <-pc.reqch
...@@ -649,6 +647,10 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err ...@@ -649,6 +647,10 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err
func (pc *persistConn) close() { func (pc *persistConn) close() {
pc.lk.Lock() pc.lk.Lock()
defer pc.lk.Unlock() defer pc.lk.Unlock()
pc.closeLocked()
}
func (pc *persistConn) closeLocked() {
pc.broken = true pc.broken = true
pc.conn.Close() pc.conn.Close()
pc.mutateHeaderFunc = nil pc.mutateHeaderFunc = nil
......
...@@ -307,10 +307,6 @@ func TestTransportServerClosingUnexpectedly(t *testing.T) { ...@@ -307,10 +307,6 @@ func TestTransportServerClosingUnexpectedly(t *testing.T) {
// Test for http://golang.org/issue/2616 (appropriate issue number) // Test for http://golang.org/issue/2616 (appropriate issue number)
// This fails pretty reliably with GOMAXPROCS=100 or something high. // This fails pretty reliably with GOMAXPROCS=100 or something high.
func TestStressSurpriseServerCloses(t *testing.T) { func TestStressSurpriseServerCloses(t *testing.T) {
if true {
t.Logf("known broken test; fix coming. Issue 2616")
return
}
if testing.Short() { if testing.Short() {
t.Logf("skipping test in short mode") t.Logf("skipping test in short mode")
return return
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment