====== C - C++ Threads - Troubleshooting - Program Crashes - Not handling exceptions in background threads ======
Exceptions thrown in one thread **cannot** be caught in another thread.
If a function executes in a separate thread forked from main and exception from this thread cannot be caught in the main thread.
----
===== Example =====
#include
#include
#include
#include
static std::exception_ptr teptr = nullptr;
void HelloWorld()
{
throw std::runtime_error("Catch me in MAIN");
}
int main()
{
try
{
std::thread t1(HelloWorld);
t1.join();
}
catch (const std::exception &ex)
{
std::cout << "Thread exited with exception: " << ex.what() << "\n";
}
return 0;
}
**NOTE:** The above program will crash and the catch block in main() will do nothing to handle the exception thrown thread t1.
The solution is to use the C++11 feature **std::exception_ptr** to capture an exception thrown in a background thread.
Here are the steps you need to do:
* Create a global instance of std::exception_ptr initialized to nullptr
* Inside the function that executes in the forked thread, catch any exception and set the std::current_exception() to the std::exception_ptr in step 1.
* Inside the main thread, check if the global exception pointer is set.
* If yes, use std::rethrow_exception(exception_ptr p) to rethrow the exception referenced by exception_ptr parameter.
Rethrowing the referenced exception does not have to be done in the same thread that generated the referenced exception in the first place, which makes this feature perfectly suited for handling exceptions across different threads.
----
===== Resolution =====
#include
#include
#include
#include
static std::exception_ptr globalExceptionPtr = nullptr;
void HelloWorld()
{
try
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
throw std::runtime_error("Catch me in MAIN");
}
catch (...)
{
// Set the global exception pointer in case of an exception.
globalExceptionPtr = std::current_exception();
}
}
int main()
{
std::thread t1(HelloWorld);
t1.join();
if (globalExceptionPtr)
{
try
{
std::rethrow_exception(globalExceptionPtr);
}
catch (const std::exception &ex)
{
std::cout << "Thread exited with exception: " << ex.what() << "\n";
}
}
return 0;
}