如何在后台运行的守护进程上使用gdb调试?

11

我正在尝试使用gdb调试我写的服务器,因为它在非常特定且罕见的情况下会出现段错误。

是否有任何方法可以让gdb在后台运行(通过quiet或batch模式?),跟踪子进程(因为我的服务器是守护进程并从主PID中分离)并在程序崩溃时自动转储核心和回溯信息(到指定文件)?


关于在Linux中生成核心转储的SO帖子 - Hassan Syed
@HassanSyed:http://vmlinux.org/jocke/mirror/www.objsw.com/docs/gdb_22.html 是一个失效的链接。 - bgoodr
7个回答

10

假设您拥有适当的权限,您可以让gdb附加到任何进程。您可以通过命令行执行以下操作:

gdb /path/to/binary _pid_

或者使用gdb中的attach命令:

attach _pid_

一旦您的守护进程已启动,您可以使用以下任一技术来附加到最终运行的PID上。 附加gdb会停止您正在跟踪的进程,因此您需要发出“continue”命令以重新启动它。

我不知道如何直接让gdb在程序崩溃时运行任意命令。这是我能想到的一个解决方法:

  1. 创建并注册一个SIGSEGV信号处理器。
  2. 告诉gdb不要在该信号上停止 (handle SIGSEGV nostop)
  3. 在信号处理程序的第一行设置断点。
  4. 从步骤3中为断点分配命令

8
为什么不能在一个持久的屏幕会话中交互式地运行进程?在调试时为何一定要是守护进程?或者在屏幕会话中运行gdb,并在它分叉后将其附加到正在运行的进程上(例如,gdb /path/to/binary -p PID_of_binary)。

这实际上是一个很好的想法,不知道为什么我没想到 :P 感谢您提供基本解决方案! - David Titarenco

3

首先,我会设置您的shell /环境以生成核心转储文件。在bash中:

ulimit -c unlimited

一旦您拥有核心转储文件,就可以使用gdb来检查堆栈跟踪:
gdb /path/to/app /path/to/core/file

2
请注意,拥有核心文件并不意味着在调试器下停止相同的进程。核心文件无法保留有关打开文件描述符或内存映射状态的信息。因此,这并不总是一个有用的建议。 - Andy Ross
1
你不能调用程序中定义的函数。 - Jason Orendorff

2
我并不是一个gdb专家,但有两件事情可以考虑:
  1. Tracepoints可能会在程序运行时提供必要的信息。
  2. 使用gdb的远程调试功能来调试正在作为守护进程运行的程序。

2

1
你可能想要了解一下Samba如何方便地进行调试;它有一个可配置的"panic action",可以暂停应用程序、通知开发人员、生成gdb等,并作为其信号处理程序的一部分运行。请参阅Samba源代码树中的lib/util/fault.c

0
我的做法是:注释掉守护进程函数调用,重新构建二进制文件,然后使用gdb运行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接