Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stop iff using a debugger

Tags:

signals

gdb

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?

like image 386
bk. Avatar asked Dec 13 '25 10:12

bk.


2 Answers

Forking a child and trying to ptrace parent is a portable UNIX way to determine whether you are being ptraced, or not, and you can then do raise(signo) only when being traced.

Note however, that this mechanism will also trigger if you are running under strace or truss, 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/status for non-0 TracerPid. This still has the same disadvantage as above.

Another Linux-specific way is to call getppid, then readlink("/proc/$PARENT_PID/exe", ...), and see if that points to GDB.

Both Linux-specific examples assume that /proc is mounted, which is usually true, but doesn't have to be.

Are there any signals that GDB uses but which I can expect that everything else ignores?

The SIGWINCH is usually ignored by non-terminal-handling programs. GDB will also ignore it, but you can make GDB stop on SIGWINCH by issuing this command:

(gdb) handle SIGWINCH stop print nopass
Signal        Stop  Print   Pass to program   Description
SIGWINCH      Yes   Yes     No                Window size changed
like image 133
Employed Russian Avatar answered Dec 15 '25 21:12

Employed Russian


The GDB documentation tells us:

When GDB runs on a "Posix system" (such as GNU or Unix machines), it interfaces with the inferior via the `ptrace' system call.

On Linux systems a process can not be traced by more than one other process. If your program forks a child that tries to attach to its parent, that will fail if you already have gdb attached to it. Signalling this failure back to the parent can be done with an exit value.

like image 36
hillu Avatar answered Dec 15 '25 19:12

hillu



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!