How to have gdb exit if program succeeds, break if program crashes? - gdb

I seem to have some kind of multithreading bug in my code that makes it crash once every 30 runs of its test suite. The test suite is non-interactive. I want to run my test suite in gdb, and have gdb exit normally if the program exits normally, or break (and show a debugging prompt) if it crashes. This way I can let the test suite run repeatedly, go grab a cup of coffee, come back, and be presented with a nice debugging prompt. How can I do this with gdb?

This is a little hacky but you could do:
gdb -ex='set confirm on' -ex=run -ex=quit --args ./a.out
If a.out terminates normally, it will just drop you out of GDB. But if you crash, the program will still be active, so GDB will typically prompt if you really want to quit with an active inferior:
Program received signal SIGABRT, Aborted.
0x00007ffff72dad05 in raise (sig=...) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
64 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
in ../nptl/sysdeps/unix/sysv/linux/raise.c
A debugging session is active.
Inferior 1 [process 15126] will be killed.
Quit anyway? (y or n)
Like I said, not pretty, but it works, as long as you haven't toggled off the prompt to quit with an active process. There is probably a way to use gdb's quit command too: it takes a numeric argument which is the exit code for the debugging session. So maybe you can use --eval-command="quit stuff", where stuff is some GDB expression that reflects whether the inferior is running or not.
This program can be used to test it out:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
if (time(NULL) % 2) {
raise(SIGINT);
}
puts("no crash");
return EXIT_SUCCESS;
}

You can also trigger a backtrace when the program crashes and let gdb exit with the return code of the child process:
gdb -return-child-result -ex run -ex "thread apply all bt" -ex "quit" --args myProgram -myProgramArg

The easiest way is to use the Python API offered by gdb:
def exit_handler(event):
gdb.execute("quit")
gdb.events.exited.connect(exit_handler)
You can even do it with one line:
(gdb) python gdb.events.exited.connect(lambda x : gdb.execute("quit"))
You can also examine the return code to ensure it's the "normal" code you expected with event.exit_code.
You can use it in conjuction with --eval-command or --command as mentioned by #acm to register the event handler from the command line, or with a .gdbinit file.

Create a file named .gdbinit and it will be used when gdb is launched.
run
quit
Run with no options:
gdb --args prog arg1...
You are telling gdb to run and quit, but it should stop processing the file if an error occurs.

Make it dump core when it crashes. If you're on linux, read the man core man page and also the ulimit builtin if you're running bash.
This way when it crashes you'll find a nice corefile that you can feed to gdb:
$ ulimit -c unlimited
$ ... run program ..., gopher coffee (or reddit ;)
$ gdb progname corefile

If you put the following lines in your ~/.gdbinit file, gdb will exit when your program exits with a status code of 0.
python
def exit_handler ( event ):
if event .exit_code == 0:
gdb .execute ( "quit" )
gdb .events .exited .connect ( exit_handler )
end
The above is a refinement of Kevin's answer.

Are you not getting a core file when it crashes? Start gdb like this 'gdb -c core' and do a stack traceback.
More likely you will want to be using Valgrind.

Related

During startup program exited normally. gdb doesn't break at breakpoints

I'm receiving this gdb error on any code I try to debug any program with gdb. Here's the simplest process that reproduces the error
Create a main.cpp file with this content:
int main(){
return 0;
}
Run g++ -g main.cpp
Run gdb a.out
Inside gdb set a break point at line 2 with break 2
In gdb run the program with run
Output:
Starting program: /tmp/test/a.out
During startup program exited normally.
This is all done with gdb on the command line. I've tried using g++ and gcc with the same result. I'm not really sure where to go from here.
gdb version = 9.2
g++ version = 9.3.0
EDIT: I figured out what is causing the issue, but not how to fix it. The issue seems to be something related to my SHELL variable. I'm currently using xonsh as my shell but when I set my SHELL environment variable back to /bin/bash everything works as expected. Is there anything I can do to fix this while using xonsh? Should I report this to xonsh, gdb, both or neither?
I'm currently using xonsh as my shell but when I set my SHELL environment variable back to /bin/bash everything works as expected. Is there anything I can do to fix this while using xonsh? Should I report this to xonsh, gdb, both or neither?
This might be your xonsh startup problem, or it might be xonsh problem, or it could be that xonsh doesn't do what GDB expects it to do.
Normally, GDB forks / execs $SHELL -c "/path/to/your/exe $args" and expects the $SHELL to exec your program (this is done so shell redirection still works under GDB).
Only after that exec will GDB start setting breakpoints, etc.
If you have some xonsh init-file, which e.g. causes xonsh to exec something else, things could go bad. So I suggest trying to remove any such ~/.xonshrc or whatever it's called file, and seeing whether that fixes the problem.
If it doesn't, it could be that xonsh e.g. forks and execs your binary in a child (grandchild of GDB) instead of doing it directly, or it could be that xonsh doesn't understand the -c ... syntax.
If you don't care about redirection, you could also ask GDB to not use $SHELL at all: set startup-with-shell off. Documentation.

How to make LLDB quit on success, wait on failure?

This is the Clang version of:
Make gdb quit automatically on successful termination?
How to have gdb exit if program succeeds, break if program crashes?
Running my application many times, programmatically, over a large number of possible inputs, I've occasionally encountered a segmentation fault.
I'd like each test invocation to be run under lldb so that I can get a backtrace for further debugging. If an invocation exits without a crash, I'd like lldb to automatically quit so that the test harness progresses to the next iteration. This way I can set the whole thing off over lunchtime and only have the suite interrupted when something crashes.
Bonus points for having lldb auto-quit in all cases, but first print a backtrace if the program crashed.
I'm currently able to automate at least the initial run command:
lldb -o run -f $CMD -- $ARGS
I'm having difficulty finding an online command reference but it looks like the -batch command line option will get you the basic "exit on success/prompt on fail" behaviour.
For a backtrace and auto-quit on failure I think you need the --source-on-crash option...
-K <filename>
--source-on-crash <filename>
When in batch mode, tells the debugger to source this file of lldb
commands if the target crashes.
So, create the command file with something like...
echo -e 'bt\nquit' > lldb.batch
and then invoke as...
lldb --batch -K lldb.batch -o run -f $CMD -- $ARGS

gdb is showing "program exited" during startup

Why is gdb showing that the program exited during its startup, so before to stop at the first breakpoint in the main function ?
Some steps:
$ gdb --cd $programhome -tui -tty $reservedtty --args myprogram
b main
r
gdb shows:
Starting program: myprogram
During startup program exited with code 1.
I already tried to break at exit() function, without success.
Why is gdb exiting before to stop at the first breakpoint in the main function
GDB is not exiting. Your program does.
It does exit before reaching main.
This can happen for a few reasons, such as:
Corrupt binary -- the kernel rejects it in execve system call for some reason and not a single instruction of the program actually runs.
The dynamic linker rejects it (e.g. because some required library or symbol is missing)
Your shell refuses to execute the program (bad ~/.bashrc, bad $PATH, etc).
You can narrow down the actual cause by running the program outside GDB (does it run?), running without ~/.bashrc, using (gdb) catch syscall exit_group (on Linux), etc.
There was a permission issue accessing the secondary terminal port.
The gdb is being started with the parameter -tty which switches the input/output to another tty port (in that case pseudo: pts).
When the two terminals are opened by different users, that problem occurs, even if after the first logon you change the user with su command, the first user logged needed to be the same among the two ttys.

How to redirect std::cin to a Linux terminal when debugging with GDB?

In Linux, GDB doesn't allow set new-console on and in stead uses something called tty. With
set inferior-tty /dev/pts/[number of an active console],
in a .gdbinit file (requires editing the number every time) it redirects std::cout, but std::cin isn't working properly. It just interprets my input as if I'm sending a bash command and reports an error, and my program continues to wait for input. I can no longer type in the console after that, so I assume std::cin is being redirected, but doesn't work properly.
I tried looking up how to launch a terminal from the application itself. I could only find this answer, which also mentions a bug that it doesn't redirect input.
Is there any way to fix this issue and redirect std::cin (and std::cout) to a Linux terminal properly when debugging?
Background info: What I'm trying to do should be simple. Print a > in front of user input before using std::cin. I have simple code in place that prints the >, flushes cout and then calls getline(). It works when just running the program normally. But sadly, GDB refuses to flush the stream when there isn't a newline, so it doesn't print the >, ignores the first character of the user input and then does prints the >, immediately followed by the error message that my program sends because of the mutilated input string.
In Windows, I've solved it by making a .gdbinit file with set new-console on. This causes GDB to use a Windows console in stead of its own and that works as intended.
If you need to start the debugging after the program has a chance to pause, just run the program in a terminal, and then gdb - your-program-pid in another terminal. Otherwise there's a sequence of steps which is faster to do than to describe.
Start two terminal windows.
In one terminal, figure out the PID of the shell. ps should tell you.
In the other terminal, use these commands
$ gdb - pid-of-the-other-shell
(gdb) br main
(gdb) c
Now you have gdb attached to your shell in another terminal. Not very useful.
In the first terminal, type at the shell prompt
$ exec your-program
Now you have one terminal running gdb and another terminal running your program under gdb, stopped at main. Bear in mind that when the program exits, its terminal window will close. If you don't want this, start a second level shell in the first terminal and attach gdb to it.
You can also use set inferior-tty command, but you must make sure the other tty exists and no other program attempts to read from it. The easiest way is to run a shell in another terminal and give it a while true; do sleep 1000; done command. Note that you may get warning: GDB: Failed to set controlling terminal: Operation not permitted messages. They are harmless.
You can use gdb's multiprocess debugging feature and a terminal emulator like xterm to do this. (gnome-terminal won't work so well as explained later)
prompt.c
#include <stdio.h>
int main()
{
enum {
N = 100,
};
char name[N];
printf("> ");
scanf("%s", name);
printf("Hi, %s\n", name);
return 0;
}
xterm.gdb
set detach-on-fork off
set target-async on
set pagination off
set non-stop on
file /usr/bin/xterm
# -ut tells xterm not to write a utmp log record
# which involves root privileges
set args -ut -e ./prompt
catch exec
run
Sample Session
$ gdb -q -x xterm.gdb
Catchpoint 1 (exec)
<...>
[New process 7073]
<...>
Thread 0x7ffff7fb2780 (LWP 7073) is executing new program: /home/scottt/Dropbox/stackoverflow/gdb-stdin-new-terminal/prompt
Reading symbols from /home/scottt/Dropbox/stackoverflow/gdb-stdin-new-terminal/prompt...done.
Catchpoint 1 (exec'd /home/scottt/Dropbox/stackoverflow/gdb-stdin-new-terminal/prompt), 0x0000003d832011f0 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) inferior 2
[Switching to inferior 2 [process 7073] (/home/scottt/Dropbox/stackoverflow/gdb-stdin-new-terminal/prompt)]
[Switching to thread 2 (Thread 0x7ffff7fb2780 (LWP 7073))]
#0 0x0000003d832011f0 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) break prompt.c:11
Breakpoint 2 at 0x4004b4: file prompt.c, line 11.
(gdb) continue &
Continuing.
(gdb)
Breakpoint 2, main () at prompt.c:11
11 printf("> ");
next
12 scanf("%s", name);
(gdb) next
13 printf("Hi, %s\n", name);
A new xterm window will appear after executing gdb -q -x xterm.gdb and you can interact with prompt inside it without interfering with GDB.
Related GDB commands:
inferior 2 switches the process GDB's debugging much like the thread command switches threads. (GDB: Debugging Multiple Inferiors and Programs)
continue & means to continue executing in the background. (GDB: Background Execution)
I used xterm because gnome-terminal uses dbus-launch to ask another process to launch the new terminal outside of the parent-child process relationship that GDB relies on.

How to automatically run the executable in GDB?

I'd like to have gdb immediately run the executable, as if I'd typed "run"
(motivation: I dislike typing "run").
One way is to pipe the command to gdb like this:
$ echo run | gdb myApp
But the problem with this approach is that you lose interactivity with gdb,
eg. if a breakpoint triggers or myApp crashes, gdb quits.
This method is discussed here.
Looking at the options in --help, I don't see a way to do this, but perhaps I'm missing something.
gdb -ex run ./a.out
If you need to pass arguments to a.out:
gdb -ex run --args ./a.out arg1 arg2 ...
EDIT:
Orion says this doesn't work on Mac OSX.
The -ex flag has been available since GDB-6.4 (released in 2005), but OSX uses Apple's fork of GDB, and the latest XCode for Leopard contains GDB 6.3.50-20050815 (Apple version gdb-967), so you are out of luck.
Building current GDB-7.0.1 release is one possible solution. Just be sure to read this.
I would use a gdb-script:
gdb -x your-script
where your-script contains something like:
file a.out
b main
r
afterwards you have the normal interactive gdb prompt
EDIT:
here is an optimization for the truly lazy:
save the script as .gdbinit in the working directory.
Afterwards you simply run gdb as
gdb
... and gdb automatically loads and executes the content of .gdbinit.
(echo r ; cat) | gdb a.out
The cat allows you keep typing after gdb breaks.
start command
This command is another good option:
gdb -ex start --args ./a.out arg1 arg2
It is like run, but also sets a temporary breakpoint at main and stops there.
This temporary breakpoint is deactivated once it is hit.
starti
There is also a related starti which starts the program and stops at the very first instruction instead, see also: Stopping at the first machine code instruction in GDB
Great when you are doing some low level stuff.
gdb -x <(echo run) --args $program $args