如何从外部分离 gdb 会话?

Posted

技术标签:

【中文标题】如何从外部分离 gdb 会话?【英文标题】:How can I detach a gdb session from outside? 【发布时间】:2021-02-24 20:06:41 【问题描述】:

我使用如下命令在后台启动一个 gdb 会话:

gdb --batch --command=/tmp/my_automated_breakpoints.gdb -p pid_of_proces> &> /tmp/gdb-results.log &

最后的& 让它在后台运行(随后shell 立即关闭,因为此命令由单个ssh 命令发出)。

我可以通过ps -aux | grep gdb 找到gdb 会话的pid

但是:我如何才能优雅地将这个 gdb 会话从正在运行的进程中分离出来,就像我使用 (gdb) detach 命令在我面前有终端会话一样?

当我使用 kill -9 gdb_pid 终止 gdb 会话(而不是正在运行的进程本身)时,之后我在运行的程序中得到了不需要的 SIGABRTs。

重新启动服务对我来说太耗时了。

如果使用此自动化脚本成功调试会话,我可以在批处理脚本中使用分离命令。然而这不是我的情况:我想在会话期间出现一些错误时分离/退出正在运行的 gdb 会话,所以我想从另一个终端会话中手动优雅地分离 gdb。

【问题讨论】:

可能相关:unix.stackexchange.com/q/31824/291769 我假设您的批处理命令正在循环运行?否则它应该结束它的协议。如果是这种情况,一种解决方法是让循环定期检查文件的存在(或不存在)。如果检测到文件,则循环应退出并分离。然后通过创建(或删除)文件来“发出信号”gdb 将是一件简单的事情。 @kaylum 有趣的想法!但是,批处理命令只是挂在continue 中并等待断点与服务的操作相匹配。所以没有真正的循环,它只是在等待...... 您能向我们展示来自 SIGABRT 的堆栈跟踪吗?据我所知,最坏的情况——GDB 不删除断点并且目标在分离后继续——将导致目标获得 SIGTRAP。 【参考方案1】:

如果您在后台从终端#1 运行gdb 命令,则始终可以通过运行命令fggdb 带回前台。然后,您可以像往常一样简单地 CTRL+C 和detach 优雅地停止调试会话。

假设终端#1现在被其他东西占用而你不能使用它,你可以发送一个SIGHUP信号给gdb进程来分离它:

sudo kill -s SIGHUP $(pidof gdb)

(如果您有多个 gdb 实例,请将 $(pidof gdb) 替换为实际 PID)

【讨论】:

我喜欢SIGHUP 方法,但遗憾的是它没有解决服务内部的SIGABRT 信号。可能杀gdb甚至都没有因果关系,我这里只是观察到一个规律。 @ElectRocnic,我刚刚在我的机器上运行了一个快速测试,并且在底层应用程序运行时向 GDB 发送 SIGHUP 将分离它并 SIGCONT 应用程序。你能解释一下:“当会话期间出现一些错误时,我想分离/退出正在运行的 gdb 会话”。这些错误是否在调试会话中? 在我在第一个请求期间分离 gdb 后,在对调试的应用程序的第二个 API 请求进行某些 io 处理期间,错误是意外 EOF。它可能真的只是服务本身。我真的相信你的答案是正确的。

以上是关于如何从外部分离 gdb 会话?的主要内容,如果未能解决你的问题,请参考以下文章

如何使 GDB 与外部程序一起工作

从外部文件访问 codeigniter 会话值

Emacs shell 中的屏幕:如何分离?

如何从给定的外部 url 获取数据会话 ID 和所有内容,而不是来自我的应用程序(路由)在 Angular 6

在 R 会话中删除/分离包

如何在 ddd (gdb) 中跳过过去的循环