summaryrefslogtreecommitdiff
path: root/indra/llcommon/llcoros.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/llcoros.cpp')
-rw-r--r--indra/llcommon/llcoros.cpp74
1 files changed, 48 insertions, 26 deletions
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index 51cf2138cb..ca2e7b38d7 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -277,15 +277,25 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl
return name;
}
-namespace
-{
-
#if LL_WINDOWS
static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
-U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
+U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop, const std::string& name)
{
+ // C++ exceptions were logged in toplevelTryWrapper, but not SEH
+ // log SEH exceptions here, to make sure it gets into bugsplat's
+ // report and because __try won't allow std::string operations
+ if (code != STATUS_MSC_EXCEPTION)
+ {
+ LL_WARNS() << "SEH crash in " << name << ", code: " << code << LL_ENDL;
+ }
+ // Handle bugsplat here, since GetExceptionInformation() can only be
+ // called from within filter for __except(filter), not from __except's {}
+ // Bugsplat should get all exceptions, C++ and SEH
+ LLApp::instance()->reportCrashToBugsplat(exception_infop);
+
+ // Only convert non C++ exceptions.
if (code == STATUS_MSC_EXCEPTION)
{
// C++ exception, go on
@@ -298,38 +308,28 @@ U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
}
}
-void sehandle(const LLCoros::callable_t& callable)
+void LLCoros::sehHandle(const std::string& name, const LLCoros::callable_t& callable)
{
__try
{
- callable();
+ LLCoros::toplevelTryWrapper(name, callable);
}
- __except (exception_filter(GetExceptionCode(), GetExceptionInformation()))
+ __except (cpp_exception_filter(GetExceptionCode(), GetExceptionInformation(), name))
{
- // convert to C++ styled exception
+ // convert to C++ styled exception for handlers other than bugsplat
// Note: it might be better to use _se_set_translator
// if you want exception to inherit full callstack
+ //
+ // in case of bugsplat this will get to exceptionTerminateHandler and
+ // looks like fiber will terminate application after that
char integer_string[512];
- sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
+ sprintf(integer_string, "SEH crash in %s, code: %lu\n", name.c_str(), GetExceptionCode());
throw std::exception(integer_string);
}
}
+#endif
-#else // ! LL_WINDOWS
-
-inline void sehandle(const LLCoros::callable_t& callable)
-{
- callable();
-}
-
-#endif // ! LL_WINDOWS
-
-} // anonymous namespace
-
-// Top-level wrapper around caller's coroutine callable.
-// Normally we like to pass strings and such by const reference -- but in this
-// case, we WANT to copy both the name and the callable to our local stack!
-void LLCoros::toplevel(std::string name, callable_t callable)
+void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& callable)
{
// keep the CoroData on this top-level function's stack frame
CoroData corodata(name);
@@ -339,12 +339,12 @@ void LLCoros::toplevel(std::string name, callable_t callable)
// run the code the caller actually wants in the coroutine
try
{
- sehandle(callable);
+ callable();
}
catch (const Stop& exc)
{
LL_INFOS("LLCoros") << "coroutine " << name << " terminating because "
- << exc.what() << LL_ENDL;
+ << exc.what() << LL_ENDL;
}
catch (const LLContinueError&)
{
@@ -355,14 +355,36 @@ void LLCoros::toplevel(std::string name, callable_t callable)
}
catch (...)
{
+#if LL_WINDOWS
+ // Any OTHER kind of uncaught exception will cause the viewer to
+ // crash, SEH handling should catch it and report to bugsplat.
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name));
+ // to not modify callstack
+ throw;
+#else
// 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
}
}
+// Top-level wrapper around caller's coroutine callable.
+// Normally we like to pass strings and such by const reference -- but in this
+// case, we WANT to copy both the name and the callable to our local stack!
+void LLCoros::toplevel(std::string name, callable_t callable)
+{
+#if LL_WINDOWS
+ // Because SEH can's have unwinding, need to call a wrapper
+ // 'try' is inside SEH handling to not catch LLContinue
+ sehHandle(name, callable);
+#else
+ toplevelTryWrapper(name, callable);
+#endif
+}
+
//static
void LLCoros::checkStop()
{