TFM
TFM

Reputation: 717

Unable to catch exception thrown by std::thread constructor

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

Answers (2)

TFM
TFM

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

the swine
the swine

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

Related Questions