Reputation:
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
Reputation: 1742
On *NIX systems (including OSX) send a signal abort SIGABRT
:
pkill -SIGABRT program_name
Upvotes: 14
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
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.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
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
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
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
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
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
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
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