使用调试器停止iff

时间:2012-12-02 18:07:22

标签: gdb signals

我想编写一个断言式宏,只有在调试器中运行程序时才会停止。 AFAIK,我的盒子上唯一可用的调试器是gdb,所以我将谈论那个。

SIGTRAP信号的文档表明它用于暂停调试器,所以我应该能够放

if (!assertion) raise(SIGTRAP);

在我的代码中。它可以在正确的位置打破GDB,但只是从命令行运行它也会暂停程序,因为bash和zsh都有助于解释“trace / breakpoint trap”信号,意味着程序应该完全停止。

是否有任何GDB使用的信号,但我可以预期其他一切都会忽略?或者是否有一种超出信号的方法可以暂停GDB中的执行而不会中断非调试器操作?

3 个答案:

答案 0 :(得分:4)

分叉一个孩子并尝试ptrace父亲是一种可移植的UNIX方式来确定您是否ptrace d,然后您可以raise(signo) 被追踪时。

但请注意,如果您在stracetruss下运行,此机制将触发,从而有效地使您的程序在其下崩溃,这可能是不可取的。< / p>

更容易实现的特定于Linux的方法是在/proc/self/status中查找非0 TracerPid。这仍然具有与上述相同的缺点。

另一种特定于Linux的方法是调用getppid,然后调用readlink("/proc/$PARENT_PID/exe", ...),并查看是否指向GDB。

两个特定于Linux的示例都假定已挂载/proc,这通常是正确的,但不一定是。

  

是否有任何GDB使用的信号,但我可以预期其他一切都会忽略?

非终端处理程序通常忽略SIGWINCH。 GDB也会忽略它,但您可以通过发出以下命令使GDB在SIGWINCH停止:

(gdb) handle SIGWINCH stop print nopass
Signal        Stop  Print   Pass to program   Description
SIGWINCH      Yes   Yes     No                Window size changed

答案 1 :(得分:1)

GDB文档告诉我们:

  

当GDB在“Posix系统”(例如GNU或Unix机器)上运行时,它通过`ptrace'系统调用与下层接口。

在Linux系统上,多个其他进程无法跟踪进程。如果您的程序分叉试图附加到其父项的子项,那么如果您已经附加了gdb,则该项将失败。可以使用退出值将此故障信号发送回父级。

答案 2 :(得分:0)

有SIGCHLD,默认情况下会被忽略。我认为gdb是由任何信号触发的,但可能不会被忽略的信号触发。你总是可以为SIGUSR1写一个信号处理程序,它什么都不做(这与忽略信号不同:程序被中断,它只是立即返回)。然后你可以发送SIGUSR1,虽然它通常会中止程序,它现在什么都不做(因为你告诉它)。有关设置信号处理程序的详细信息,请参阅sigaction上的文档。