Reputation: 717
I have a C++ program imposing a memory limit via setrlimit. Depending on the parameters it may throw std::bad_alloc at various locations which I want to handle.
I use multiple threads via std::thread. I have some code along the lines of this:
std::thread* worker;
try
{
worker=new std::thread[NUM_THREADS];
for(int i=0;i<NUM_THREADS;++i)
{
worker[i]=std::thread(&ThisClass::SomeMemberFunc, this, SomeArg...);
}
}
catch(...)
{
std::cout << "exception in thread creation" << std::endl;
}
So thread creation is wrapped in try/catch. Yet it happens that the program abort with:
terminate called after throwing an instance of 'St9bad_alloc'
what(): std::bad_alloc
When I use gdb and set a breakpoint at abort(), the backtrace looks like:
#0 __GI_abort () at abort.c:53
#1 0x00007ffff717269d in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2 0x00007ffff7170846 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007ffff7170873 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007ffff7127cfb in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007ffff73c2e9a in start_thread (arg=0x7ffff3e86700) at pthread_create.c:308
#6 0x00007ffff6bd93fd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112
#7 0x0000000000000000 in ?? ()
Now, how is this possible?
Upvotes: 2
Views: 2115
Reputation: 717
It is, in fact, SomeMemberFunc
that throws the exception.
nosid suggested to use std::async
instead of std::thread
to catch the exception on the call-side.
I decided to store the exception thrown by SomeMemberFunc
in an std::exception_ptr
via std::current_exception()
. After joining the thread, I check the exception pointer.
Upvotes: 1
Reputation: 11031
The threads will not catch each other's exceptions. There is no notion of a "parent" thread, as such thread might not even exist anymore by the time an exception is thrown in a "child" thread.
If you require the threads to pass exceptions, you need to implement it yourself by wrapping the SomeMemberFunc
in a try-catch block and copying the caught exception to a variable of the "parent" thread, where it is later rethrown. Note that you will need to block the calling thread (the "parent") while the other threads are running, in order to enforce the hierarchy (the thread itself can be reused to call one of SomeMemberFunc
in parallel so you don't waste a thread completely).
Upvotes: 2