What if you need to catch an exception in a worker thread and re-throw it in the main thread that’s waiting for the worker to finish?
std::futureworks this way. If you spawn a future on a new thread using
std::async(std::launch::async, ...);and that future’s worker throws an exception, when you later call
get()on the future it will emit that exception.
You do it by wrapping the worker thread’s function in
try { /* CODE */ } catch(...) {} and capturing the current exception pointer (std::exception_ptr) using
std::current_exception. You can then re-throw the captured exception using the pointer and
std::rethrow_exception. Below is an example that illustrates this technique. Just remember, if you have multiple worker threads make sure to have multiple
std::exception_ptrinstances; one per worker thread.
#include#include #include #include #include using namespace std; int main(int, char**) { exception_ptr ep = nullptr; thread t([&]() { try { stringstream str; str << this_thread::get_id(); throw runtime_error(str.str().c_str()); } catch(...) { ep = current_exception(); } }); t.join(); if(ep != nullptr) { try { rethrow_exception(ep); } catch(exception& e) { cout << "Thread " << this_thread::get_id() << " caught exception from thread " << e.what() << endl; } } }
Thread 0x1048d75c0 caught exception from thread 0x700001cf3000
Program output.
One common problem with doing this (or capturing and rethrowing in general) is that you lose the original thread’s stack when the main thread eventually cores.
I like to core programmatically before unwinding because of this.
https://vorbrodt.blog/2019/03/15/printing-stack-traces/ 🙂