How to dump goroutine stacktraces?

Go

Go Problem Overview


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?

Go Solutions


Solution 1 - Go

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)

Solution 2 - Go

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

Solution 3 - Go

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])
    }
}()

Solution 4 - Go

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+</kbd>.

Solution 5 - Go

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.

Solution 6 - Go

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 :)

Solution 7 - Go

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

pkill -SIGABRT program_name

Solution 8 - Go

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.

Solution 9 - Go

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]))
}

Solution 10 - Go

You can use this:

kill -3 YOUR_PROCESS_PID_ID

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser972946View Question on Stackoverflow
Solution 1 - GoIntermernetView Answer on Stackoverflow
Solution 2 - GolnmxView Answer on Stackoverflow
Solution 3 - GoBryanView Answer on Stackoverflow
Solution 4 - GoRodolfo CarvalhoView Answer on Stackoverflow
Solution 5 - GoRobert KajicView Answer on Stackoverflow
Solution 6 - GoØyvind SkaarView Answer on Stackoverflow
Solution 7 - GoKyle KloepperView Answer on Stackoverflow
Solution 8 - GoInanc GumusView Answer on Stackoverflow
Solution 9 - GoDavid TootillView Answer on Stackoverflow
Solution 10 - GoM. GopalView Answer on Stackoverflow