summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2025-03-25 14:30:29 +0200
committerAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2025-03-25 22:24:02 +0200
commitd484fff77d73931e70c896b9a88db547c4922dbd (patch)
treecaef518c7d3d58b0a51b6821f66f42f8feb0e4f6 /indra/llcommon
parente1d6b57733ceb050ab243886261f663948da7e13 (diff)
#3596 Don't supress exceptions in WorkQueue
We need those to know about problems.
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/workqueue.cpp83
1 files changed, 80 insertions, 3 deletions
diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp
index 6066e74fb5..dace95aaf2 100644
--- a/indra/llcommon/workqueue.cpp
+++ b/indra/llcommon/workqueue.cpp
@@ -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)