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?
Forking a child and trying to
ptraceparent is a portable UNIX way to determine whether you are beingptraced, or not, and you can then doraise(signo)only when being traced.Note however, that this mechanism will also trigger if you are running under
straceortruss, effectively making your program crash under them, which is probably undesirable.A Linux-specific way that is easier to implement is to look in
/proc/self/statusfor non-0TracerPid. This still has the same disadvantage as above.Another Linux-specific way is to call
getppid, thenreadlink("/proc/$PARENT_PID/exe", ...), and see if that points to GDB.Both Linux-specific examples assume that
/procis mounted, which is usually true, but doesn’t have to be.The
SIGWINCHis usually ignored by non-terminal-handling programs. GDB will also ignore it, but you can make GDB stop onSIGWINCHby issuing this command: