2

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?

5
  • What if writing to cout throws? Commented May 23, 2014 at 17:57
  • 1
    I looks as if the exception is thrown from SomeMemberFunc in the newly created thread, not from the thread constructor itself. Can you wrap the body of SomeMemberFunc into a try-catch block? Commented May 23, 2014 at 17:58
  • 3
    Not the answer, but use std::vector<std::thread> instead of std::thread *. Commented May 23, 2014 at 18:01
  • Thanks Alan and nosid. It was in fact SomeMemberFunc that threw. I already had suspected that and had a function try/catch around it. But I totally missed that in fact a part of my handling in the catch block could throw again. I just can't answer myself for 8 hours... Commented May 23, 2014 at 18:59
  • 1
    You can try using std::async(std::launch::async, ...) instead of std::thread. With the former, you can catch the exception also on the call-side. Commented May 23, 2014 at 19:02

2 Answers 2

2

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).

Sign up to request clarification or add additional context in comments.

Comments

1

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.