diff options
Diffstat (limited to 'src/runtime/debug/stack.go')
| -rw-r--r-- | src/runtime/debug/stack.go | 82 |
1 files changed, 8 insertions, 74 deletions
diff --git a/src/runtime/debug/stack.go b/src/runtime/debug/stack.go index ab12bffa6e..952d834bc4 100644 --- a/src/runtime/debug/stack.go +++ b/src/runtime/debug/stack.go @@ -7,92 +7,26 @@ package debug import ( - "bytes" - "fmt" - "io/ioutil" "os" "runtime" ) -var ( - dunno = []byte("???") - centerDot = []byte("·") - dot = []byte(".") - slash = []byte("/") -) - // PrintStack prints to standard error the stack trace returned by Stack. func PrintStack() { - os.Stderr.Write(stack()) + os.Stderr.Write(Stack()) } // Stack returns a formatted stack trace of the goroutine that calls it. // For each routine, it includes the source line information and PC value, // then attempts to discover, for Go functions, the calling function or -// method and the text of the line containing the invocation. -// -// Deprecated: Use package runtime's Stack instead. +// method. func Stack() []byte { - return stack() -} - -// stack implements Stack, skipping 2 frames -func stack() []byte { - buf := new(bytes.Buffer) // the returned data - // As we loop, we open files and read them. These variables record the currently - // loaded file. - var lines [][]byte - var lastFile string - for i := 2; ; i++ { // Caller we care about is the user, 2 frames up - pc, file, line, ok := runtime.Caller(i) - if !ok { - break + buf := make([]byte, 1024) + for { + n := runtime.Stack(buf, false) + if n < len(buf) { + return buf[:n] } - // Print this much at least. If we can't find the source, it won't show. - fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc) - if file != lastFile { - data, err := ioutil.ReadFile(file) - if err != nil { - continue - } - lines = bytes.Split(data, []byte{'\n'}) - lastFile = file - } - line-- // in stack trace, lines are 1-indexed but our array is 0-indexed - fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line)) - } - return buf.Bytes() -} - -// source returns a space-trimmed slice of the n'th line. -func source(lines [][]byte, n int) []byte { - if n < 0 || n >= len(lines) { - return dunno - } - return bytes.Trim(lines[n], " \t") -} - -// function returns, if possible, the name of the function containing the PC. -func function(pc uintptr) []byte { - fn := runtime.FuncForPC(pc) - if fn == nil { - return dunno - } - name := []byte(fn.Name()) - // The name includes the path name to the package, which is unnecessary - // since the file name is already included. Plus, it has center dots. - // That is, we see - // runtime/debug.*T·ptrmethod - // and want - // *T.ptrmethod - // Since the package path might contains dots (e.g. code.google.com/...), - // we first remove the path prefix if there is one. - if lastslash := bytes.LastIndex(name, slash); lastslash >= 0 { - name = name[lastslash+1:] - } - if period := bytes.Index(name, dot); period >= 0 { - name = name[period+1:] + buf = make([]byte, 2*len(buf)) } - name = bytes.Replace(name, centerDot, dot, -1) - return name } |
