如何转储所有Go进程的堆栈?

时间:2014-04-29 03:14:45

标签: go

Go进程正在运行。我想

  1. 为每个goroutine转储堆栈跟踪
  2. 来自外部,不依赖于我添加到其源代码中的任何内容
  3. 没有杀死它。
  4. 我该怎么做?

    这应该很容易 - 请求功能:https://code.google.com/p/go/issues/detail?id=2516并根据该线程的结论实施。那是两年多以前的事了。但是问题线程和提交都没有包含关于如何调用此功能的任何提示。

    功能请求提到SIGQUIT调用JVM上的相应功能,但不是这样;至少在go1.2上,SIGQUIT做#1和#2但也杀死了这个过程。

    前一段时间有人问过相关问题:How to dump goroutine stacktraces? 但他们没有明确要求#2或#3,没有一个答案符合#2,他们接受了不符合#2的答案。所以这是一个不同的问题。

2 个答案:

答案 0 :(得分:10)

您可以使用以下代码设置这样的处理程序:

import (
    "fmt"
    "os"
    "os/signal"
    "runtime"
    "syscall"
)

func main() {
    sigChan := make(chan os.Signal)
    go func() {
        stacktrace := make([]byte, 8192)
        for _ = range sigChan {
            length := runtime.Stack(stacktrace, true)
            fmt.Println(string(stacktrace[:length]))
        }
    }()
    signal.Notify(sigChan, syscall.SIGQUIT)


    ...
}

现在将捕获SIGQUIT信号并将其发送到给定频道。然后使用runtime.Stack函数将堆栈跟踪格式化为准备好的缓冲区(如果它大于缓冲区,它将被截断),然后打印。

答案 1 :(得分:3)

如果您使用的是net / http,则可以通过调试处理程序访问goroutines。如果您查看以下来源

http://golang.org/src/pkg/runtime/pprof/pprof.go

您会在第62行看到个人资料goroutineProfile。此个人资料通过writeGoroutine写出。如果使用debug> = 2调用writeGoroutine,那么它将写出所有goroutine。

你应该能够curl http://localhost:<port>/debug/pprof/goroutine?debug=2让所有goroutine被抛弃。不幸的是,我没有看到任何可以调用该代码的信号处理程序的引用,但是您可以查看pprof如何在上面的源代码中使用runtime.Stack来自己实现这一点。