我想编写一个断言式宏,只有在调试器中运行程序时才会停止。 AFAIK,我的盒子上唯一可用的调试器是gdb,所以我将谈论那个。
SIGTRAP信号的文档表明它用于暂停调试器,所以我应该能够放
if (!assertion) raise(SIGTRAP);
在我的代码中。它可以在正确的位置打破GDB,但只是从命令行运行它也会暂停程序,因为bash和zsh都有助于解释“trace / breakpoint trap”信号,意味着程序应该完全停止。
是否有任何GDB使用的信号,但我可以预期其他一切都会忽略?或者是否有一种超出信号的方法可以暂停GDB中的执行而不会中断非调试器操作?
答案 0 :(得分:4)
分叉一个孩子并尝试ptrace
父亲是一种可移植的UNIX方式来确定您是否ptrace
d,然后您可以raise(signo)
被追踪时。
但请注意,如果您在strace
或truss
下运行,此机制将也触发,从而有效地使您的程序在其下崩溃,这可能是不可取的。< / 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
上的文档。