3

I'd like to write an assert-style macro that stops only if I am running the program in a debugger. AFAIK, the only available debugger on my box is gdb, so I'll talk about that one.

The documentation for the SIGTRAP signal indicates that it is intended for pausing the debugger, so I should be able to put

if (!assertion) raise(SIGTRAP);

in my code. It works to break GDB at the right point, but just running this from the command line also halts the program, as both bash and zsh helpfully interpret the "trace/breakpoint trap" signal to mean that the program should halt entirely.

Are there any signals that GDB uses but which I can expect that everything else ignores? Or is there a method beyond signals to pause execution in GDB without disrupting non-debugger operation?

4

3 回答 3

4

分叉一个孩子并尝试做ptrace父母是一种可移植的 UNIX 方式来确定你是否是ptraced,然后你raise(signo) 只能在被跟踪时这样做。

但是请注意,如果您在or下运行,此机制也会触发,从而有效地使您的程序在它们下崩溃,这可能是不可取的。stracetruss

一种更容易实现的特定于 Linux 的方法是查找/proc/self/status0 TracerPid. 这仍然具有与上述相同的缺点。

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

这两个特定于 Linux 的示例都假定/proc已挂载,这通常是正确的,但并非必须如此。

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

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

(gdb) handle SIGWINCH stop print nopass
Signal        Stop  Print   Pass to program   Description
SIGWINCH      Yes   Yes     No                Window size changed
于 2012-12-02T18:47:53.083 回答
1

GDB 文档告诉我们:

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

在 Linux 系统上,一个进程不能被多个其他进程跟踪。如果您的程序派生了一个尝试附加到其父级的子级,那么如果您已经附加了 gdb,则该子级将失败。可以使用退出值向父级发送此失败信号。

于 2012-12-02T18:30:36.270 回答
0

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

于 2012-12-02T18:14:50.787 回答