Reputation: 972
I'm using assert
from <cassert>
to check invariants in my multithreaded C++11 program. When the assertion fails, I'd like to be able to inspect the state of the failing function, along with still-intact backtrace, variable state, etc. at the time of the failed assertion. The issue seems be some interaction between SIGABRT
and my threads, as my std::thread
s are pthread_kill
ed, presumably by some default signal handler. How can I pause gdb right at the time of the failed assertion?
Here are some things I've tried:
set a catchpoint on SIGABRT
. This catch does occur, but it's too late (in __pthread_kill
).
defined __assert_fail
, which is extern
declared in <assert.h>
, and set a gdb breakpoint on it. This is never caught so presumably the pthread is being killed before this is called (?).
What's the recommended approach here?
Upvotes: 2
Views: 1289
Reputation: 972
If you need a breakpoint on assert for some reason, Klaus's answer to break on __assert_fail
is absolutely correct.
However, it turns out that setting a breakpoint to see stack traces in gdb on multithreaded programs is simply not necessary at all, as gdb already breaks on SIGABRT
and switches the the aborting thread. In my case I had a misconfigured set of libraries that lead to this red herring. If you are trying to see stack traces from aborted code (SIGABRT
) in gdb using multithreaded programs, you do not need to do anything in gdb, assuming the default signal handlers are in place.
FYI, you can see the default signal handlers by running info signals
, and the same for just SIGABRT
by running info signals SIGABRT
. On my machine, I see this, which shows that the program will be stopped, etc. If for some reason your SIGABRT
signal handler is not set up to stop on SIGABRT
, you need to change that setting. More info at https://sourceware.org/gdb/onlinedocs/gdb/Signals.html.
(gdb) info signals SIGABRT
Signal Stop Print Pass to program Description
SIGABRT Yes Yes Yes Aborted
Upvotes: 0
Reputation: 25593
I did the following:
Example programm:
#include <cassert>
void f2()
{
assert(0);
}
void f1()
{
f2();
}
int main()
{
f1();
}
Now I set a breakpoint to f2 in hope I can step down to the assert with stepi
later:
gdb > break f2
gdb > run
Breakpoint 11, f2 () at main.cpp:5
gdb > stepi // several times!!!!
0x080484b0 in __assert_fail@plt ()
Ahhh! As we can see stepi
goes to symbol which tells us that there is a function with that name. So set simply a breakpoint for __assert_fail@plt
gdb > break __assert_fail@plt
gdb > run
Breakpoint 11, f2 () at main.cpp:5
(gdb) bt
#0 0x080484b0 in __assert_fail@plt ()
#1 0x080485f7 in f2 () at main.cpp:5
#2 0x08048602 in f1 () at main.cpp:10
#3 0x0804861b in main () at main.cpp:15
Works for me!
Upvotes: 4