diff options
author | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2025-03-03 22:49:52 +0200 |
---|---|---|
committer | Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> | 2025-03-04 17:23:05 +0200 |
commit | ed394cd5a07d69e9007ad50819a01911645cadcd (patch) | |
tree | e227353861b270196117c98f829bea9f3f5e7496 | |
parent | a1ccb44c15b484787bce34e06adb0396bfc6d2a4 (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.cpp | 27 | ||||
-rw-r--r-- | indra/llcommon/llcoros.h | 27 | ||||
-rw-r--r-- | indra/newview/llappviewer.cpp | 2 |
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(); } } |