Commit 61ed384a authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

net/http: make CloseNotifier channel buffered to not leak goroutines

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/8911044
parent 994c486a
......@@ -1370,6 +1370,7 @@ func TestContentLengthZero(t *testing.T) {
}
func TestCloseNotifier(t *testing.T) {
defer afterTest(t)
gotReq := make(chan bool, 1)
sawClose := make(chan bool, 1)
ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
......@@ -1405,6 +1406,31 @@ For:
ts.Close()
}
func TestCloseNotifierChanLeak(t *testing.T) {
defer afterTest(t)
req := []byte(strings.Replace(`GET / HTTP/1.0
Host: golang.org
`, "\n", "\r\n", -1))
for i := 0; i < 20; i++ {
var output bytes.Buffer
conn := &rwTestConn{
Reader: bytes.NewReader(req),
Writer: &output,
closec: make(chan bool, 1),
}
ln := &oneConnListener{conn: conn}
handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
// Ignore the return value and never read from
// it, testing that we don't leak goroutines
// on the sending side:
_ = rw.(CloseNotifier).CloseNotify()
})
go Serve(ln, handler)
<-conn.closec
}
}
func TestOptions(t *testing.T) {
uric := make(chan string, 2) // only expect 1, but leave space for 2
mux := NewServeMux()
......
......@@ -146,7 +146,7 @@ func (c *conn) closeNotify() <-chan bool {
c.mu.Lock()
defer c.mu.Unlock()
if c.closeNotifyc == nil {
c.closeNotifyc = make(chan bool)
c.closeNotifyc = make(chan bool, 1)
if c.hijackedv {
// to obey the function signature, even though
// it'll never receive a value.
......
......@@ -76,6 +76,7 @@ func afterTest(t *testing.T) {
"created by net/http/httptest.(*Server).Start": "an httptest.Server",
"timeoutHandler": "a TimeoutHandler",
"net.(*netFD).connect(": "a timing out dial",
").noteClientGone(": "a closenotifier sender",
}
var stacks string
for i := 0; i < 4; i++ {
......
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