From 454d5b48715772889db12d142486e75a3a4dfed3 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 26 Feb 2025 15:58:18 +0200 Subject: #3591 Reprot SEH directly to bugsplat Rethrowing SEH via std::exception results ina callstack that ends at rethrow. --- indra/llcommon/llapp.h | 2 +- indra/llcommon/llcoros.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 3d18864b80..57f5a112d9 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -282,7 +282,7 @@ public: LLRunner& getRunner() { return mRunner; } #ifdef LL_WINDOWS - virtual void reportCrashToBugsplat(void* pExcepInfo /*EXCEPTION_POINTERS*/) { } + virtual bool reportCrashToBugsplat(void* pExcepInfo /*EXCEPTION_POINTERS*/) { return false; } #endif public: diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 1539b48bd3..ab56a3d3b7 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -310,18 +310,20 @@ namespace static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific -U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) +U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS* exception_infop) { if (code == STATUS_MSC_EXCEPTION) { // C++ exception, go on return EXCEPTION_CONTINUE_SEARCH; } - else + else if (!LLApp::instance()->reportCrashToBugsplat((void*)exception_infop)) { // handle it return EXCEPTION_EXECUTE_HANDLER; } + + return EXCEPTION_CONTINUE_SEARCH; } void sehandle(const LLCoros::callable_t& callable) -- cgit v1.2.3 From 39610cbfb381eec0b144f22cd1b34a4ff6911322 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 26 Feb 2025 19:11:57 +0200 Subject: #3591 Remove now pointless rethrow --- indra/llcommon/llcoros.cpp | 36 +++++++++--------------------------- indra/llcommon/llcoros.h | 27 --------------------------- 2 files changed, 9 insertions(+), 54 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index ab56a3d3b7..b16f166d28 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -228,22 +228,6 @@ 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; @@ -312,14 +296,19 @@ static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS* exception_infop) { - if (code == STATUS_MSC_EXCEPTION) + 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 if (!LLApp::instance()->reportCrashToBugsplat((void*)exception_infop)) + else { - // handle it + // handle it, convert to std::exception return EXCEPTION_EXECUTE_HANDLER; } @@ -381,14 +370,7 @@ void LLCoros::toplevel(std::string name, callable_t callable) // viewer will carry on. LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); } - 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()); - } + // uncaught exception by default will cause std::terminate() } //static diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index c3820ae987..913414fbc1 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -170,19 +170,6 @@ 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 @@ -327,20 +314,6 @@ 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 mExceptionQueue; S32 mStackSize; -- cgit v1.2.3 From ed394cd5a07d69e9007ad50819a01911645cadcd Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 3 Mar 2025 22:49:52 +0200 Subject: #3591 rethrow should be mac specific Jumped the gun a bit, since reportCrashToBugsplat is OS specific, restore rethrow for other systems. --- indra/llcommon/llcoros.cpp | 27 ++++++++++++++++++++++++++- indra/llcommon/llcoros.h | 27 +++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) (limited to 'indra/llcommon') 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 @@ -170,6 +170,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 @@ -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 mExceptionQueue; S32 mStackSize; -- cgit v1.2.3