1
0
mirror of https://github.com/golang/go synced 2024-11-21 20:14:52 -07:00

http: catch panics

R=rsc
CC=golang-dev
https://golang.org/cl/4559067
This commit is contained in:
Brad Fitzpatrick 2011-06-02 12:00:26 -07:00
parent 191a6bfc5e
commit 2a8ea0d1b5
2 changed files with 47 additions and 1 deletions

View File

@ -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) {
} }
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) {
} }
} }
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) {

View File

@ -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 (
"net" "net"
"os" "os"
"path" "path"
"runtime"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@ -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 {