I have a worker thread that is constantly running, created & managed through a std::thread
. At the top level of my worker thread, I have a try/catch block with a while loop inside it. If an exception leaks through to the top level of the thread, I catch it and store it in a std::exception_ptr
, which is a member of the class that also owns the non-static thread function:
// In class header (inside class declaration)
std::exception_ptr m_threadException;
// In class CPP file
void MyClass::MyThreadFunction()
{
try {
while (true) {
// Do thread stuff
}
}
catch (std::exception const& e) {
m_threadException = std::current_exception();
}
}
Once the thread dies due to this kind of exception, my class (which is also primarily used by the main thread) doesn't know it yet. My plan was to add thread checkpoints to the start of all the class's main functions, like so:
void MyClass::SomethingMainThreadCalls()
{
if (m_threadException) {
std::rethrow_exception(m_threadException);
m_threadException = nullptr; // Somehow reset it back to null; not sure if this will work
}
// Do normal function stuff
}
Assuming this is even a good idea, there's a possible race condition between when my main thread is checking if the exception_ptr is null (when calling SomethingMainThreadCalls()
) and when the worker thread assigns to it. I haven't found any information (haven't checked the C++11 draft yet) about whether or not this is inherently thread safe (guaranteed by the standard) or if I am responsible for thread synchronization in this case.
If the latter, is using std::atomic
a good idea to keep it simple? Example:
std::atomic<std::exception_ptr> m_threadException;
Something like that? Hoping that the answer to my question also involves some good recommendations and information on best practice here. Thanks in advance.
There is no special statement about exception_ptr
with regards to its thread safety in the standard. As such, it provides the default standard guarantee: accessing separate instances are fine, accessing the same instance is not.
I would suggest using atomic<bool>
instead (if for no other reason than that exception_ptr
is not trivially copyable and therefore can't be put in an atomic<T>
) to let the other code know that the exception_ptr
has been set. You'll be fine so long as:
m_threadException
before setting the flagm_threadException
after checking the flagm_threadException
exactly once.The standard doesn't specify what is the implementation of std::exception_ptr
, so the thread safeness of std::exception_ptr
is also unspecified.
just wrap the exception pointer with some lock and the code will be fine.
Just tried to do this, but std::atomic
requires a trivially copyable type, std::exception_ptr
is not. You should get compilation error as I do (when using MSVC VS2019, C++14).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With