summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2025-03-03 22:49:52 +0200
committerAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2025-03-04 17:23:05 +0200
commited394cd5a07d69e9007ad50819a01911645cadcd (patch)
treee227353861b270196117c98f829bea9f3f5e7496
parenta1ccb44c15b484787bce34e06adb0396bfc6d2a4 (diff)
#3591 rethrow should be mac specific
Jumped the gun a bit, since reportCrashToBugsplat is OS specific, restore rethrow for other systems.
-rw-r--r--indra/llcommon/llcoros.cpp27
-rw-r--r--indra/llcommon/llcoros.h27
-rw-r--r--indra/newview/llappviewer.cpp2
3 files changed, 55 insertions, 1 deletions
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index b16f166d28..ea2d102de9 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -228,6 +228,22 @@ std::string LLCoros::logname()
return data.mName.empty()? data.getKey() : data.mName;
}
+void LLCoros::saveException(const std::string& name, std::exception_ptr exc)
+{
+ mExceptionQueue.emplace(name, exc);
+}
+
+void LLCoros::rethrow()
+{
+ if (! mExceptionQueue.empty())
+ {
+ ExceptionData front = mExceptionQueue.front();
+ mExceptionQueue.pop();
+ LL_WARNS("LLCoros") << "Rethrowing exception from coroutine " << front.name << LL_ENDL;
+ std::rethrow_exception(front.exception);
+ }
+}
+
void LLCoros::setStackSize(S32 stacksize)
{
LL_DEBUGS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL;
@@ -370,7 +386,16 @@ void LLCoros::toplevel(std::string name, callable_t callable)
// viewer will carry on.
LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name));
}
- // uncaught exception by default will cause std::terminate()
+#ifndef LL_WINDOWS
+ catch (...)
+ {
+ // Stash any OTHER kind of uncaught exception in the rethrow() queue
+ // to be rethrown by the main fiber.
+ LL_WARNS("LLCoros") << "Capturing uncaught exception in coroutine "
+ << name << LL_ENDL;
+ LLCoros::instance().saveException(name, std::current_exception());
+ }
+#endif // ! LL_WINDOWS
}
//static
diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h
index 913414fbc1..c3820ae987 100644
--- a/indra/llcommon/llcoros.h
+++ b/indra/llcommon/llcoros.h
@@ -171,6 +171,19 @@ public:
static std::string getName();
/**
+ * rethrow() is called by the thread's main fiber to propagate an
+ * exception from any coroutine into the main fiber, where it can engage
+ * the normal unhandled-exception machinery, up to and including crash
+ * reporting.
+ *
+ * LLCoros maintains a queue of otherwise-uncaught exceptions from
+ * terminated coroutines. Each call to rethrow() pops the first of those
+ * and rethrows it. When the queue is empty (normal case), rethrow() is a
+ * no-op.
+ */
+ void rethrow();
+
+ /**
* This variation returns a name suitable for log messages: the explicit
* name for an explicitly-launched coroutine, or "mainN" for the default
* coroutine on a thread.
@@ -314,6 +327,20 @@ private:
void toplevel(std::string name, callable_t callable);
struct CoroData;
static CoroData& get_CoroData(const std::string& caller);
+ void saveException(const std::string& name, std::exception_ptr exc);
+
+ struct ExceptionData
+ {
+ ExceptionData(const std::string& nm, std::exception_ptr exc):
+ name(nm),
+ exception(exc)
+ {}
+ // name of coroutine that originally threw this exception
+ std::string name;
+ // the thrown exception
+ std::exception_ptr exception;
+ };
+ std::queue<ExceptionData> mExceptionQueue;
S32 mStackSize;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index a05466b476..e8546d422b 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1402,6 +1402,8 @@ bool LLAppViewer::doFrame()
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df suspend");
// give listeners a chance to run
llcoro::suspend();
+ // if one of our coroutines threw an uncaught exception, rethrow it now
+ LLCoros::instance().rethrow();
}
}