GDB:Ctrl+C不像通常那样中断进程,而是终止程序。

39

通常情况下,当您通过GDB运行程序时,您可以按Ctrl+C来中断它,例如,如果它陷入无限循环,您需要获取一个回溯。

我正在调试一个程序(恰好是xmms2d),但在这个程序中,当我按Ctrl+C时,它会被视为未运行GDB - 程序会干净地关闭,然后GDB告诉我程序正常退出。

如何恢复通常的GDB行为,使得Ctrl+C可以中断程序?还是有其他方法可以在GDB中产生与Ctrl+C相同的反应?


你的GDB版本和操作系统是什么?你能提供一个最小的C程序,以便在其中也发生这种情况吗? - Ciro Santilli OurBigBook.com
每年有1000多人来到这里寻找答案 :-) 新问题可以被关闭为此问题的副本。但如果你忘记了细节,我不会责怪你。 - Ciro Santilli OurBigBook.com
6个回答

36

很遗憾,当底层进程挂起时,我无法像那样解除 gdb 的阻塞。gdb 和我的进程仍然挂起 :-( 有其他提示吗? - lethalman
1
对于其他人想知道, '<pid>' 在这里是指下属进程(不是 gdb)。 - ricab

10
在 gdb 提示符下,您可以执行“handle SIGINT stop”命令,以便gdb捕获CTRL-C。

如果被调试的进程正在调用 sigwait(),则此方法无效。默认情况下应设置 handle SIGINIT stop - maxschlepzig
1
我甚至没有怀疑@maxschlepzig的智慧的理由......然而,sunil的答案帮助我意识到handle SIGINT pass是Google让我来这里解决(相反的)问题的解决方案。 - Martin Dorey

4
我曾经遇到了由SDL信号处理器引起的问题,它干扰了gdb。我发现一种解决方法是在启动gdb时使用以下方法:
start
call sigignore(2)
continue

现在应用程序将忽略所有的CTRL-C。
如果您要“attach”到某个进程并想在调试后将其恢复到原始状态,可以执行以下操作:
set $oldcallback = signal(2, 0)
call sigignore(2)
continue

完成后:

call signal(2, $oldcallback)
detach

我猜这会导致应用程序忽略该信号,但对于我来说gdb仍然无法停止。 - Carlo Wood

1
我遇到过类似的问题,但已经解决了。
首先,编写一个gdb脚本,文件名为sighandler.gdb。该脚本文件位于项目目录中:
gdb_sigwait/src/sighandler.gdb

然后,在编译器初始化文件(~/.gdbinit)中source上述脚本文件,例如:

source ~/gdb_sigwait/src/sighandler.gdb

gdb脚本太长了。 因此,我创建了一个github项目来介绍和存储相关代码: https://github.com/fairyfar/gdb_sigwait


嗨,FairyFar。欢迎来到Stack Overflow!如果您还没有这样做,请参加tour - Captain Hat
答案应该是自包含的,链接应该是为了补充/澄清内容。请更新您的答案,以便解决方案包含在文本中。 - Captain Hat
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

1
请注意,在rlwrap下运行GDB会破坏其正确拦截^C的能力。如果您正在这样做,请尝试在没有rlwrap的情况下运行它。

如果你是正确的,那么这就是一个bug。我无法重现它 - 你能给个例子或者更好的方式是提交一个bug报告吗?顺便说一下:gdb使用readline,那么为什么还要使用rlwrap呢? - Hans Lub
@HansLub 我很烦恼 GDB 在不同会话之间不能记住我的命令历史记录,所以我使用了 rlwrap。很抱歉目前我没有时间来生成一个错误报告。 - Radon Rosborough

0
您可以使用以下命令更改GDB的输入/输出目标:
gdb -tty = /dev/tty1

这并没有解决问题。输出确实会到达另一个终端,但是当您在gdb的终端上按下Ctrl+C时,被调试的程序仍然会捕获信号并干净地退出,就好像您根本没有更改tty一样。 - Malvineous

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