// Copyright (c) 2017 Uber Technologies, Inc.//// Permission is hereby granted, free of charge, to any person obtaining a copy// of this software and associated documentation files (the "Software"), to deal// in the Software without restriction, including without limitation the rights// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell// copies of the Software, and to permit persons to whom the Software is// furnished to do so, subject to the following conditions://// The above copyright notice and this permission notice shall be included in// all copies or substantial portions of the Software.//// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN// THE SOFTWARE.package stackimport ()const_defaultBufferSize = 64 * 1024// 64 KiB// Stack represents a single Goroutine's stack.typeStackstruct {idintstatestringfirstFunctionstringfullStack *bytes.Buffer}// ID returns the goroutine ID.func ( Stack) () int {return .id}// State returns the Goroutine's state.func ( Stack) () string {return .state}// Full returns the full stack trace for this goroutine.func ( Stack) () string {return .fullStack.String()}// FirstFunction returns the name of the first function on the stack.func ( Stack) () string {return .firstFunction}func ( Stack) () string {returnfmt.Sprintf("Goroutine %v in state %v, with %v on top of the stack:\n%s", .id, .state, .firstFunction, .Full())}func ( bool) []Stack {var []Stackvar *Stack := bufio.NewReader(bytes.NewReader(getStackBuffer()))for { , := .ReadString('\n')if == io.EOF {break }if != nil {// We're reading using bytes.NewReader which should never fail.panic("bufio.NewReader failed on a fixed string") }// If we see the goroutine header, start a new stack. := falseifstrings.HasPrefix(, "goroutine ") {// flush any previous stackif != nil { = append(, *) } , := parseGoStackHeader() = &Stack{id: ,state: ,fullStack: &bytes.Buffer{}, } = true } .fullStack.WriteString()if ! && .firstFunction == "" { .firstFunction = parseFirstFunc() } }if != nil { = append(, *) }return}// All returns the stacks for all running goroutines.func () []Stack {returngetStacks(true)}// Current returns the stack for the current goroutine.func () Stack {returngetStacks(false)[0]}func ( bool) []byte {for := _defaultBufferSize; ; *= 2 { := make([]byte, )if := runtime.Stack(, ); < {return [:] } }}func ( string) string { = strings.TrimSpace()if := strings.LastIndex(, "("); > 0 {return [:] }panic(fmt.Sprintf("function calls missing parents: %q", ))}// parseGoStackHeader parses a stack header that looks like:// goroutine 643 [runnable]:\n// And returns the goroutine ID, and the state.func ( string) ( int, string) { = strings.TrimSuffix(, ":\n") := strings.SplitN(, " ", 3)iflen() != 3 {panic(fmt.Sprintf("unexpected stack header format: %q", )) } , := strconv.Atoi([1])if != nil {panic(fmt.Sprintf("failed to parse goroutine ID: %v in line %q", [1], )) } = strings.TrimSuffix(strings.TrimPrefix([2], "["), "]")return , }
The pages are generated with Goldsv0.4.9. (GOOS=linux GOARCH=amd64)