21

如何在使用 MONO 运行的挂起应用程序中显示线程(堆栈跟踪)?

我知道我可以使用托管堆栈资源管理器 (MSE) 在 .NET 中完成此操作。因为应用程序只与 MONO 一起挂起,所以我需要用 MONO 来做。

或者有什么其他的想法我可以找到悬挂的地方吗?

4

2 回答 2

25

假设您使用的是 Linux/Unix,而不是 Windows,请向您的程序发送 SIGQUIT 信号。这可以通过

kill -QUIT $PID

其中 $PID 是您的程序的 pid。然后 Mono 会将所有线程的堆栈跟踪转储到标准输出。请注意,尽管该过程在此之后保持运行,但您不应期望它保持可用/稳定。

有关一些背景信息,请参阅http://en.wikipedia.org/wiki/SIGQUIT

注意:线程转储不会kill在您运行命令的终端窗口中打印出来。它将出现在单声道进程的标准错误中。

于 2010-01-15T00:04:24.940 回答
2

也可以使用 GDB 快速获取托管堆栈跟踪。执行gdb;如果您不是 root 或调试用户拥有的进程,请使用 sudo。

执行我从 mono-project.org 上的调试 Mono页面获得的这个脚本:

handle SIGXCPU SIG33 SIG35 SIGPWR nostop noprint

define mono_stack
 set $mono_thread = mono_thread_current ()
 if ($mono_thread == 0x00)
   printf "No mono thread associated with this thread\n"
 else
   set $ucp = malloc (sizeof (ucontext_t))
   call (void) getcontext ($ucp)
   call (void) mono_print_thread_dump ($ucp)
   call (void) free ($ucp)
 end
end

如果您愿意,可以将这些命令放入您的文件中~/.gdbinit,这样您就不必一直复制和粘贴。

现在附加到您的 PID:

attach 12345

请注意,整个过程现在已暂停,因此如果您在生产环境中执行此操作,建议编写脚本以使其尽可能快。

要获取堆栈跟踪,请mono_stack按上述定义执行。请注意,您不会在 gdb 中看到输出,而是在 stdout 中看到输出。如果您使用 upstart 运行您的进程,您只需编辑 upstart 作业以将console log其记录到/var/log/upstart.

但是,您可能对除主线程之外的另一个线程感兴趣。为此,请执行info threads以获取您的线程列表并thread 2切换到线程#2。有关线程调试的更多信息,请参阅GDB 文档中的多线程调试程序。

完成后,执行quit,您的程序将继续工作。

于 2016-08-31T12:31:22.807 回答