开发者

Make gdb quit automatically on successful termination?

开发者 https://www.devze.com 2023-01-16 21:07 出处:网络
I use a debugging script that runs several related processes in succession with the debugger. I\'m currently using -x to execute several commands automatically (such as run). How can I make gdb quit a

I use a debugging script that runs several related processes in succession with the debugger. I'm currently using -x to execute several commands automatically (such as run). How can I make gdb quit automatically when the debugged process successfully terminates? Adding a quit command to the command file will cause that command to be handled not just on successful termination, but when errors occur also (when I'd rather take over at that point).

Here's an extract of what's going on:

+ gdb -return-child-result -x gdbbatch --args ./mkfs.cpfs /dev/loop0
GNU gdb (GDB) 7.1-ubuntu
Reading symbols from /home/matt/cpfs/mkfs.cpfs...done.

Program exited normally.
Breakpoint 2 at 0x805224f: file开发者_StackOverflow log.c, line 32.
(gdb)

Contents of gdbbatch:

start
b cpfs_log if level >= WARNING


I think I have found a complete solution to your question in connection to looking for something similar in How to make gdb send an external notification on receiving a signal?. None of the other guys here seem to have mentioned or discovered gdb hooks.

Based on Matthew's tip about $_exitcode, this is now my app/.gdbinit that achieves exactly the behavior wanted; normal quit on successful termination and drop to gdb prompt, send email, whatnot on everything else:

set $_exitcode = -999
set height 0
handle SIGTERM nostop print pass
handle SIGPIPE nostop
define hook-stop
    if $_exitcode != -999
        quit
    else
        shell echo | mail -s "NOTICE: app has stopped on unhandled signal" root
    end
end
echo .gdbinit: running app\n
run


gdb sets $_exitcode when the program successfully terminates. You can make use of that - set it to an unlikely value at the start of your script, and only quit at the end if it has changed:

set $_exitcode = -999
# ...
run
# ...
if $_exitcode != -999
  quit
end

(Setting $_exitcode to an unlikely value is a bit ugly, but it will otherwise not be defined at all if the program doesn't terminate, and there doesn't seem to be any obvious way of asking "is this variable defined?" in a conditional.)


GDB has a different "language" for interacting with automated programs called GDB/MI (detailed here), but unfortunately, it doesn't look like it supports conditionals, and is expected to run from other programs with parsing and branching. So, it looks like Expect is the easiest (or at least a working) solution:

$ cat gdbrunner
#!/usr/bin/expect -f

#spawn gdb -return-child-result --args ./mkfs.cpfs /dev/loop0
spawn gdb -return-child-result --args [lindex $argv 0]

#send "start\n"
#send "b cpfs_log if level >= WARNING"
send "run\n"

expect {
    normally\.         { send "quit\n" }
    "exited with code" { interact -nobuffer }
}

I tested this with the simple programs:

$ cat prog1.c
int main(void) { return 0; }
$ cat prog2.c
int main(void) { return 1; }

With the following results:

$ ./gdbrunner ./prog1
spawn gdb -return-child-result --args ./prog1
run
(gdb) run
Starting program: /home/foo/prog1

Program exited normally.
(gdb) quit
$ ./gdbrunner ./prog2
spawn gdb -return-child-result --args ./prog2
run
(gdb) run
Starting program: /home/foo/prog2

Program exited with code 01.
(gdb)

Essentially, you have to parse the output and branch using something else. This would of course work with any other program capable of handling input/output of another process, but the above expect script should get you started, if you don't mind Tcl. It should be a little better, and expect the first (gdb) prompt, but works due to stdin buffering.

You can also modify it to use that GDB/MI interface with the -i command-line argument to GDB; its commands and output are a bit more readily parsable, if you will expand to need more advanced features, as you can see in the previously linked documentation.

0

精彩评论

暂无评论...
验证码 换一张
取 消