【问题标题】:Debugging a running daemon using gdb使用 gdb 调试正在运行的守护进程
【发布时间】:2013-04-16 15:33:40
【问题描述】:

我正在开发一个作为守护进程运行的高流量网络 C 服务器应用程序。在某些情况下,应用程序崩溃(总是没有核心)。如何使用 gdb 调试正在运行的守护程序以找到生成 SIGSEGV 的位置?

解释性说明:

  1. 我知道如何使用 gdb 将附加命令附加到正在运行的进程

  2. 附加到进程后,它会停止。如果我运行然后“继续”,如果程序没有崩溃,gdb 将保持阻塞状态。如果我按 CTRL-C,进程将退出,我无法简单地分离 gdb。

所以问题是:有没有办法在不卡住 gdb 的情况下继续进程,但如果进程没有崩溃则能够分离?

【问题讨论】:

  • 您是否尝试过更改核心转储设置,例如ulimit 命令?和/或运行调试版本?或者可能添加更多日志记录以缩小崩溃的可能位置?
  • 我已经尝试了所有的可能性。该进程在 Ubuntu 服务器上作为新贵服务运行,并在服务启动时设置为特定用户。 limits.conf 包含该用户的 nofile 和 core 的无限值。我在 /etc/sysctl.conf 中设置了 fs.suid_dumpable 和 kernel.core_uses_pid 我添加了更多日志记录,但它是一个高流量服务器,它产生的输出太多。

标签: c linux gdb daemon


【解决方案1】:

调试应用程序的另一种方法是使用核心文件通过 GDB 进行调试。

要在分段发生时生成核心文件,您可以按照以下步骤操作:

1) 将以下参数复制到运行守护程序的脚本中。

ulimit -c unlimited
mkdir -p <path_to_core_file>, eg : /etc/user/ankit/corefiles
chmod 777 /etc/user/ankit/corefiles
echo "/etc/user/ankit/corefiles/%e.%s.core" > /proc/sys/kernel/core_pattern

2) 使用脚本运行您的应用程序并等待创建核心转储文件。获得核心转储后,您可以按照上述步骤使用 gdb 进行调试。

3) 使用 GDB 获取回溯

gdb -c <core_file>, where core_file is the file generated after segmentation fault

4) 回溯

接下来,我们想知道程序崩溃时堆栈是什么。在 gdb 提示符下运行 bt 会给你一个回溯。如果 gdb 没有为二进制文件加载符号,那么它会抛出一个带有问号的错误,类似于“??????”。要解决此问题,您必须加载符号。

这是加载调试符号的方法。

symbol-file /path/to/binary
sharedlibrary

5) 获取所有线程的 backTrace

thread apply all bt full

注意:确保使用调试符号编译二进制文件。

【讨论】:

    【解决方案2】:

    这个页面attach/detachdetach 命令可以在gdb 中工作。

    如果您想在应用程序中捕获分段错误,则必须从调试器中运行该应用程序。然后当信号被捕获时,您可以使用wherebt 查看应用程序的堆栈跟踪。应用程序出现故障后当然不能继续使用了,应该如何恢复呢?如果您希望很快触发故障,您可以附加到正在运行的进程并再次在调试器中等待故障。

    如果您想要在故障发生后进行堆栈跟踪,那么您确实需要一个核心文件,因为没有进程可以附加到。现在,如果您的守护程序作为系统的一部分启动,则可能很难获得转储核心的配置,而且您可能不希望其他应用程序到处留下核心转储。因此,我建议停止系统守护程序并在您的用户空间中重新启动它,然后您可以允许它转储核心。如果它作为系统的一部分启动确实很重要,那么查看守护程序的启动是否仅限于单个子 shell 并在该子 shell 中使用 ulimit -c 为核心转储。

    【讨论】:

    • 我知道,但是运行“继续”命令后,退出 gdb 的唯一方法是按 CTRL-C,它会停止正在运行的进程。
    • 使用detach 代替continue,然后使用quit。为我工作。
    • 我明白,但如果进程崩溃,我希望能够获得回溯。
    • 我在答案中添加了更多内容,希望对您有所帮助。
    【解决方案3】:

    尝试异步模式并“继续 &”:

    将下方保存到 non-stop.gdb

    set target-async on
    set pagination off
    set non-stop on
    

    然后运行:

    $ gdb -x non-top.gdb
    (gdb) !pgrep YOUR-DAEMON
    1234
    (gdb) attach 1234
    (gdb) continue -a &
    (gdb)
    

    【讨论】:

    • 谢谢。我会试试这个并发布反馈。
    猜你喜欢
    • 1970-01-01
    • 2011-01-04
    • 1970-01-01
    • 2023-03-02
    • 2011-01-19
    • 1970-01-01
    • 2021-10-27
    • 2014-07-15
    • 1970-01-01
    相关资源
    最近更新 更多