I have a problem with uncaught exceptions in a std::thread. Normally
when there's an uncaught exception, the backtrace in gdb will show where
the actual exception was thrown. When using std::thread, the exception
seems to be thrown from even before the thread's main function is
called, making it almost impossible to find out what actually happened.
An example should illustrace nicely:
#include <stdexcept>
#include <thread>
void foo()
{
throw std::runtime_error("foo");
}
int
main()
{
thread t(foo);
t.join();
}
Compile using "g++ -Wall -std=c++0x -g tmp.cpp", and run "gdb a.out":
(gdb) r
Starting program: /boris/home/tobias/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[New Thread 0x7ffff7dc1700 (LWP 2427)]
terminate called after throwing an instance of 'std::runtime_error'
what(): foo
Program received signal SIGABRT, Aborted.
[Switching to Thread 0x7ffff7dc1700 (LWP 2427)]
0x00000034906362a5 in raise () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install
boost-thread-1.47.0-3.fc16.x86_64 glibc-2.14.90-14.x86_64
libgcc-4.6.2-1.fc16.x86_64 libstdc++-4.6.2-1.fc16.x86_64
(gdb) bt
#0 0x00000034906362a5 in raise () from /lib64/libc.so.6
#1 0x0000003490637bbb in abort () from /lib64/libc.so.6
#2 0x000000349aabbf8d in __gnu_cxx::__verbose_terminate_handler()
() from /usr/lib64/libstdc++.so.6
#3 0x000000349aaba146 in ?? () from /usr/lib64/libstdc++.so.6
#4 0x000000349aaba173 in std::terminate() () from
/usr/lib64/libstdc++.so.6
#5 0x000000349aa70bdb in ?? () from /usr/lib64/libstdc++.so.6
#6 0x0000003490a07d90 in start_thread () from /lib64/libpthread.so.0
#7 0x00000034906eeddd in clone () from /lib64/libc.so.6
As you can see, foo() is not in the backtrace. Now, if I use
boost::thread (1.47.0) instead:
#include <stdexcept>
#include <thread>
#include <boost/thread.hpp>
void foo()
{
throw std::runtime_error("foo");
}
int
main()
{
boost::thread t(foo);
t.join();
}
The backtrace in gdb now looks like this:
#0 0x00000034906362a5 in raise () from /lib64/libc.so.6
#1 0x0000003490637bbb in abort () from /lib64/libc.so.6
#2 0x000000349aabbf8d in __gnu_cxx::__verbose_terminate_handler()
() from /usr/lib64/libstdc++.so.6
#3 0x000000349aaba146 in ?? () from /usr/lib64/libstdc++.so.6
#4 0x000000349aaba173 in std::terminate() () from
/usr/lib64/libstdc++.so.6
#5 0x000000349aaba26e in __cxa_throw () from /usr/lib64/libstdc++.so.6
#6 0x0000000000403039 in foo () at tmp2.cpp:6
#7 0x0000000000405b1f in boost::detail::thread_data<void
(*)()>::run (this=0x60a0d0)
at /usr/include/boost/thread/detail/thread.hpp:61
#8 0x00007ffff7dd5bf9 in ?? () from
/usr/lib64/libboost_thread-mt.so.1.47.0
#9 0x0000003490a07d90 in start_thread () from /lib64/libpthread.so.0
#10 0x00000034906eeddd in clone () from /lib64/libc.so.6
That's more like it. Is the std::thread behaviour a bug, or am I missing
something? Though the C++11 standard seems to allow the stack to be
unwound before std::terminate is called, it exceptionally unhelpful.
I've search but not been able to find any explanation.
I've tested this using both gcc 4.6.2 and 4.5.1 on Linux x64_64.
/Tobias