Commit 2a8ea0d1 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

http: catch panics

R=rsc
CC=golang-dev
https://golang.org/cl/4559067
parent 191a6bfc
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
. "http" . "http"
"http/httptest" "http/httptest"
"io/ioutil" "io/ioutil"
"log"
"os" "os"
"net" "net"
"reflect" "reflect"
...@@ -432,6 +433,9 @@ func TestSetsRemoteAddr(t *testing.T) { ...@@ -432,6 +433,9 @@ func TestSetsRemoteAddr(t *testing.T) {
} }
func TestChunkedResponseHeaders(t *testing.T) { func TestChunkedResponseHeaders(t *testing.T) {
log.SetOutput(ioutil.Discard) // is noisy otherwise
defer log.SetOutput(os.Stderr)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header().Set("Content-Length", "intentional gibberish") // we check that this is deleted w.Header().Set("Content-Length", "intentional gibberish") // we check that this is deleted
fmt.Fprintf(w, "I am a chunked response.") fmt.Fprintf(w, "I am a chunked response.")
...@@ -755,6 +759,20 @@ func TestZeroLengthPostAndResponse(t *testing.T) { ...@@ -755,6 +759,20 @@ func TestZeroLengthPostAndResponse(t *testing.T) {
} }
} }
func TestHandlerPanic(t *testing.T) {
log.SetOutput(ioutil.Discard) // is noisy otherwise
defer log.SetOutput(os.Stderr)
ts := httptest.NewServer(HandlerFunc(func(ResponseWriter, *Request) {
panic("intentional death for testing")
}))
defer ts.Close()
_, err := Get(ts.URL)
if err == nil {
t.Logf("expected an error")
}
}
func BenchmarkClientServer(b *testing.B) { func BenchmarkClientServer(b *testing.B) {
b.StopTimer() b.StopTimer()
ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) { ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
......
...@@ -6,12 +6,12 @@ ...@@ -6,12 +6,12 @@
// TODO(rsc): // TODO(rsc):
// logging // logging
// post support
package http package http
import ( import (
"bufio" "bufio"
"bytes"
"crypto/rand" "crypto/rand"
"crypto/tls" "crypto/tls"
"fmt" "fmt"
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
"net" "net"
"os" "os"
"path" "path"
"runtime"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
...@@ -475,6 +476,33 @@ func (c *conn) close() { ...@@ -475,6 +476,33 @@ func (c *conn) close() {
// Serve a new connection. // Serve a new connection.
func (c *conn) serve() { func (c *conn) serve() {
defer func() {
err := recover()
if err == nil {
return
}
c.rwc.Close()
// TODO(rsc,bradfitz): this is boilerplate. move it to runtime.Stack()
var buf bytes.Buffer
fmt.Fprintf(&buf, "http: panic serving %v: %v\n", c.remoteAddr, err)
for i := 1; i < 20; i++ {
pc, file, line, ok := runtime.Caller(i)
if !ok {
break
}
var name string
f := runtime.FuncForPC(pc)
if f != nil {
name = f.Name()
} else {
name = fmt.Sprintf("%#x", pc)
}
fmt.Fprintf(&buf, " %s %s:%d\n", name, file, line)
}
log.Print(buf.String())
}()
for { for {
w, err := c.readRequest() w, err := c.readRequest()
if err != nil { if err != nil {
......
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