Commit 91934ff5 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

net/http: fix server connection leak on Handler's panic(nil)

If a handler did a panic(nil), the connection was never closed.

Fixes #4050

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/6971049
parent 07e706f8
...@@ -918,15 +918,19 @@ func TestZeroLengthPostAndResponse(t *testing.T) { ...@@ -918,15 +918,19 @@ func TestZeroLengthPostAndResponse(t *testing.T) {
} }
} }
func TestHandlerPanicNil(t *testing.T) {
testHandlerPanic(t, false, nil)
}
func TestHandlerPanic(t *testing.T) { func TestHandlerPanic(t *testing.T) {
testHandlerPanic(t, false) testHandlerPanic(t, false, "intentional death for testing")
} }
func TestHandlerPanicWithHijack(t *testing.T) { func TestHandlerPanicWithHijack(t *testing.T) {
testHandlerPanic(t, true) testHandlerPanic(t, true, "intentional death for testing")
} }
func testHandlerPanic(t *testing.T, withHijack bool) { func testHandlerPanic(t *testing.T, withHijack bool, panicValue interface{}) {
// Unlike the other tests that set the log output to ioutil.Discard // Unlike the other tests that set the log output to ioutil.Discard
// to quiet the output, this test uses a pipe. The pipe serves three // to quiet the output, this test uses a pipe. The pipe serves three
// purposes: // purposes:
...@@ -955,7 +959,7 @@ func testHandlerPanic(t *testing.T, withHijack bool) { ...@@ -955,7 +959,7 @@ func testHandlerPanic(t *testing.T, withHijack bool) {
} }
defer rwc.Close() defer rwc.Close()
} }
panic("intentional death for testing") panic(panicValue)
})) }))
defer ts.Close() defer ts.Close()
...@@ -968,7 +972,7 @@ func testHandlerPanic(t *testing.T, withHijack bool) { ...@@ -968,7 +972,7 @@ func testHandlerPanic(t *testing.T, withHijack bool) {
_, err := pr.Read(buf) _, err := pr.Read(buf)
pr.Close() pr.Close()
if err != nil { if err != nil {
t.Fatal(err) t.Error(err)
} }
done <- true done <- true
}() }()
...@@ -978,6 +982,10 @@ func testHandlerPanic(t *testing.T, withHijack bool) { ...@@ -978,6 +982,10 @@ func testHandlerPanic(t *testing.T, withHijack bool) {
t.Logf("expected an error") t.Logf("expected an error")
} }
if panicValue == nil {
return
}
select { select {
case <-done: case <-done:
return return
......
...@@ -716,6 +716,7 @@ func (c *conn) serve() { ...@@ -716,6 +716,7 @@ func (c *conn) serve() {
c.rwc.Close() c.rwc.Close()
} }
}() }()
defer c.close()
if tlsConn, ok := c.rwc.(*tls.Conn); ok { if tlsConn, ok := c.rwc.(*tls.Conn); ok {
if err := tlsConn.Handshake(); err != nil { if err := tlsConn.Handshake(); err != nil {
...@@ -791,7 +792,6 @@ func (c *conn) serve() { ...@@ -791,7 +792,6 @@ func (c *conn) serve() {
break break
} }
} }
c.close()
} }
func (w *response) sendExpectationFailed() { func (w *response) sendExpectationFailed() {
......
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