user972946
user972946

Reputation:

How to dump goroutine stacktraces?

I have Java background, and I love to use signal QUIT to inspect Java thread dump.

How to let Golang print out all goroutines stack trace?

Upvotes: 163

Views: 176914

Answers (11)

Kyle Kloepper
Kyle Kloepper

Reputation: 1742

On *NIX systems (including OSX) send a signal abort SIGABRT:

pkill -SIGABRT program_name

Upvotes: 14

zeroboo
zeroboo

Reputation: 8945

Package errors allows you to dump the error with stack trace. For example with the function WithStack

WithStack annotates err with a stack trace at the point WithStack was called

package main

import (
"fmt"

"github.com/pkg/errors"
)

func main() {
    cause := errors.New("whoops")
    err := errors.WithStack(cause)
    fmt.Printf("%+v", err)
}

Upvotes: 0

M. Gopal
M. Gopal

Reputation: 444

You can use this:

kill -3 YOUR_PROCESS_PID_ID

Upvotes: 2

Inanc Gumus
Inanc Gumus

Reputation: 27889

By default, press ^\ keys ( CTRL+\ ) to dump the stack traces of all goroutines.


Otherwise, for more granular control, you can use panic. The simple way as of Go 1.6+:

go func() {
    s := make(chan os.Signal, 1)
    signal.Notify(s, syscall.SIGQUIT)
    <-s
    panic("give me the stack")
}()

Then, run your program like so:

# Press ^\ to dump the stack traces of all the user-created goroutines
$ GOTRACEBACK=all go run main.go

If you also want to print go runtime goroutines:

$ GOTRACEBACK=system go run main.go

Here are all the GOTRACEBACK options:

  • GOTRACEBACK=none omits the goroutine stack traces entirely.
  • GOTRACEBACK=single (the default) behaves as described above.
  • GOTRACEBACK=all adds stack traces for all user-created goroutines.
  • GOTRACEBACK=system is like all but adds stack frames for run-time functions and shows goroutines created internally by the run-time.
  • GOTRACEBACK=crash is like system but crashes in an operating system-specific manner instead of exiting. For example, on Unix systems, the crash raises SIGABRT to trigger a core dump.

Here is the documentation

The GOTRACEBACK variable controls the amount of output generated when a Go program fails due to an unrecovered panic or an unexpected runtime condition.

By default, a failure prints a stack trace for the current goroutine, eliding functions internal to the run-time system, and then exits with exit code 2. The failure prints stack traces for all goroutines if there is no current goroutine or the failure is internal to the run-time.

For historical reasons, the GOTRACEBACK settings 0, 1, and 2 are synonyms for none, all, and system, respectively.

The runtime/debug package's SetTraceback function allows increasing the amount of output at run time, but it cannot reduce the amount below that specified by the environment variable. See https://golang.org/pkg/runtime/debug/#SetTraceback.

Upvotes: 10

Bryan
Bryan

Reputation: 12190

To mimic the Java behaviour of stack-dump on SIGQUIT but still leaving the program running:

go func() {
    sigs := make(chan os.Signal, 1)
    signal.Notify(sigs, syscall.SIGQUIT)
    buf := make([]byte, 1<<20)
    for {
        <-sigs
        stacklen := runtime.Stack(buf, true)
        log.Printf("=== received SIGQUIT ===\n*** goroutine dump...\n%s\n*** end\n", buf[:stacklen])
    }
}()

Upvotes: 45

Rodolfo Carvalho
Rodolfo Carvalho

Reputation: 1967

Similar to Java, SIGQUIT can be used to print a stack trace of a Go program and its goroutines.
A key difference, however, is that by default sending SIGQUIT to Java programs do not terminate them, while Go programs do exit.

This approach requires no code change to print a stack trace of all goroutines of existing programs.

The environment variable GOTRACEBACK (see documentation of the runtime package) controls the amount of output generated. For example, to include all goroutines, set GOTRACEBACK=all.

The printing of the stack trace is triggered by an unexpected runtime condition (unhandled signal), originally documented in this commit, making it available since at least Go 1.1.


Alternatively, if modifying source code is an option, see other answers.


Note that in a Linux terminal, SIGQUIT can be conveniently sent with the key combination Ctrl+\.

Upvotes: 51

lnmx
lnmx

Reputation: 11154

There is an HTTP frontend for the runtime/pprof package mentioned in Intermernet's answer. Import the net/http/pprof package to register an HTTP handler for /debug/pprof:

import _ "net/http/pprof"
import _ "net/http"

Start an HTTP listener if you do not have one already:

go func() {
    log.Println(http.ListenAndServe("localhost:6060", nil))
}()

Then point a browser to http://localhost:6060/debug/pprof for a menu, or http://localhost:6060/debug/pprof/goroutine?debug=2 for a full goroutine stack dump.

There are other fun things you can learn about your running code this way too. Check out the blog post for examples and more details: http://blog.golang.org/profiling-go-programs

Upvotes: 55

&#216;yvind Skaar
&#216;yvind Skaar

Reputation: 2328

Press CTRL+\

(If you run it in a terminal and just want to kill your program and dump the go routines etc)

I found this question looking for the key sequence. Just wanted a quick and easy way to tell if my program is leaking go routines :)

Upvotes: 32

David Tootill
David Tootill

Reputation: 571

It's necessary to use the length returned by runtime.Stack() to avoid printing a bunch of empty lines after your stack trace. The following recovery function prints a nicely formatted trace:

if r := recover(); r != nil {
    log.Printf("Internal error: %v", r))
    buf := make([]byte, 1<<16)
    stackSize := runtime.Stack(buf, true)
    log.Printf("%s\n", string(buf[0:stackSize]))
}

Upvotes: 5

Intermernet
Intermernet

Reputation: 19378

To print the stack trace for the current goroutine, use PrintStack() from runtime/debug.

PrintStack prints to standard error the stack trace returned by Stack.

For example:

import(
   "runtime/debug"
)
...    
debug.PrintStack()

To print the stack trace for all goroutines use Lookup and WriteTo from runtime/pprof.

func Lookup(name string) *Profile
// Lookup returns the profile with the given name,
// or nil if no such profile exists.

func (p *Profile) WriteTo(w io.Writer, debug int) error
// WriteTo writes a pprof-formatted snapshot of the profile to w.
// If a write to w returns an error, WriteTo returns that error.
// Otherwise, WriteTo returns nil.

Each Profile has a unique name. A few profiles are predefined:

goroutine - stack traces of all current goroutines
heap - a sampling of all heap allocations
threadcreate - stack traces that led to the creation of new OS threads
block - stack traces that led to blocking on synchronization primitives

For example:

pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)

Upvotes: 181

Robert Kajic
Robert Kajic

Reputation: 9077

You can use runtime.Stack to get the stack trace of all goroutines:

buf := make([]byte, 1<<16)
runtime.Stack(buf, true)
fmt.Printf("%s", buf)

From the documentation:

func Stack(buf []byte, all bool) int

Stack formats a stack trace of the calling goroutine into buf and returns the number of bytes written to buf. If all is true, Stack formats stack traces of all other goroutines into buf after the trace for the current goroutine.

Upvotes: 33

Related Questions