diff options
Diffstat (limited to 'src/pkg/http')
-rw-r--r-- | src/pkg/http/pprof/pprof.go | 14 | ||||
-rw-r--r-- | src/pkg/http/transfer.go | 20 |
2 files changed, 32 insertions, 2 deletions
diff --git a/src/pkg/http/pprof/pprof.go b/src/pkg/http/pprof/pprof.go index bc79e2183..917c7f877 100644 --- a/src/pkg/http/pprof/pprof.go +++ b/src/pkg/http/pprof/pprof.go @@ -26,6 +26,7 @@ package pprof import ( "bufio" + "bytes" "fmt" "http" "os" @@ -88,10 +89,14 @@ func Profile(w http.ResponseWriter, r *http.Request) { func Symbol(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain; charset=utf-8") + // We have to read the whole POST body before + // writing any output. Buffer the output here. + var buf bytes.Buffer + // We don't know how many symbols we have, but we // do have symbol information. Pprof only cares whether // this number is 0 (no symbols available) or > 0. - fmt.Fprintf(w, "num_symbols: 1\n") + fmt.Fprintf(&buf, "num_symbols: 1\n") var b *bufio.Reader if r.Method == "POST" { @@ -109,14 +114,19 @@ func Symbol(w http.ResponseWriter, r *http.Request) { if pc != 0 { f := runtime.FuncForPC(uintptr(pc)) if f != nil { - fmt.Fprintf(w, "%#x %s\n", pc, f.Name()) + fmt.Fprintf(&buf, "%#x %s\n", pc, f.Name()) } } // Wait until here to check for err; the last // symbol will have an err because it doesn't end in +. if err != nil { + if err != os.EOF { + fmt.Fprintf(&buf, "reading request: %v\n", err) + } break } } + + w.Write(buf.Bytes()) } diff --git a/src/pkg/http/transfer.go b/src/pkg/http/transfer.go index 98c32bab6..0fa8bed43 100644 --- a/src/pkg/http/transfer.go +++ b/src/pkg/http/transfer.go @@ -439,9 +439,29 @@ type body struct { hdr interface{} // non-nil (Response or Request) value means read trailer r *bufio.Reader // underlying wire-format reader for the trailer closing bool // is the connection to be closed after reading body? + closed bool +} + +// ErrBodyReadAfterClose is returned when reading a Request Body after +// the body has been closed. This typically happens when the body is +// read after an HTTP Handler calls WriteHeader or Write on its +// ResponseWriter. +var ErrBodyReadAfterClose = os.NewError("http: invalid Read on closed request Body") + +func (b *body) Read(p []byte) (n int, err os.Error) { + if b.closed { + return 0, ErrBodyReadAfterClose + } + return b.Reader.Read(p) } func (b *body) Close() os.Error { + if b.closed { + return nil + } + defer func() { + b.closed = true + }() if b.hdr == nil && b.closing { // no trailer and closing the connection next. // no point in reading to EOF. |