#3596 Don't supress exceptions in WorkQueue

We need those to know about problems.
meow-7.2.2
Andrey Kleshchev 2025-03-25 14:30:29 +02:00 committed by Andrey Kleshchev
parent e1d6b57733
commit d484fff77d
1 changed files with 80 additions and 3 deletions

View File

@ -17,6 +17,7 @@
// std headers
// external library headers
// other Linden headers
#include "llapp.h"
#include "llcoros.h"
#include LLCOROS_MUTEX_HEADER
#include "llerror.h"
@ -102,19 +103,95 @@ std::string LL::WorkQueueBase::makeName(const std::string& name)
return STRINGIZE("WorkQueue" << num);
}
namespace
{
#if LL_WINDOWS
static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS* exception_infop)
{
if (LLApp::instance()->reportCrashToBugsplat((void*)exception_infop))
{
// Handled
return EXCEPTION_CONTINUE_SEARCH;
}
else if (code == STATUS_MSC_EXCEPTION)
{
// C++ exception, go on
return EXCEPTION_CONTINUE_SEARCH;
}
else
{
// handle it, convert to std::exception
return EXCEPTION_EXECUTE_HANDLER;
}
return EXCEPTION_CONTINUE_SEARCH;
}
void cpphandle(const LL::WorkQueueBase::Work& work)
{
// SE and C++ can not coexists, thus two handlers
try
{
work();
}
catch (const LLContinueError&)
{
// Any uncaught exception derived from LLContinueError will be caught
// here and logged. This coroutine will terminate but the rest of the
// viewer will carry on.
LOG_UNHANDLED_EXCEPTION(STRINGIZE("LLContinue in work queue"));
}
}
void sehandle(const LL::WorkQueueBase::Work& work)
{
__try
{
// handle stop and continue exceptions first
cpphandle(work);
}
__except (exception_filter(GetExceptionCode(), GetExceptionInformation()))
{
// convert to C++ styled exception
char integer_string[512];
sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
throw std::exception(integer_string);
}
}
#endif // LL_WINDOWS
} // anonymous namespace
void LL::WorkQueueBase::callWork(const Work& work)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
#ifdef LL_WINDOWS
// can not use __try directly, toplevel requires unwinding, thus use of a wrapper
sehandle(work);
#else // LL_WINDOWS
try
{
work();
}
catch (...)
catch (LLContinueError&)
{
// No matter what goes wrong with any individual work item, the worker
// thread must go on! Log our own instance name with the exception.
LOG_UNHANDLED_EXCEPTION(getKey());
}
catch (...)
{
// Stash any other kind of uncaught exception to be rethrown by main thread.
LL_WARNS("LLCoros") << "Capturing uncaught exception in WorkQueueBase "
<< getKey() << LL_ENDL;
LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
main_queue->post(
// Bind the current exception rethrow it in main loop.
[exc = std::current_exception()]() { std::rethrow_exception(exc); });
}
#endif // else LL_WINDOWS
}
void LL::WorkQueueBase::error(const std::string& msg)