summaryrefslogtreecommitdiff
path: root/indra/llcommon/llexception.cpp
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2024-05-28 13:22:05 -0400
committerNat Goodspeed <nat@lindenlab.com>2024-05-28 13:22:05 -0400
commit5ed8df22cd59680a685c4ada7daa5555bf59d4fe (patch)
treeaffa9679e891608f9689c780cdd00710e5ea2c95 /indra/llcommon/llexception.cpp
parent71d777ea126e7f02cb46c11bdb606094ca06f75c (diff)
Fix up llexception.h's cross-platform SEH wrapper.
Introduce AlwaysReturn<void> specialization, which always discards any result of calling the specified callable with specified args. Derive new Windows_SEH_exception from LLException, not std::runtime_error. Put the various SEH functions in LL::seh nested namespace, e.g. LL::seh::catcher() as the primary API. Break out more levels of Windows SEH handler to work around the restrictions on functions containing __try/__except. The triadic catcher() overload now does little save declare a std::string stacktrace before forwarding the call to catcher_inner(), passing a reference to stacktrace along with the trycode, filter and handler functions. catcher_inner() accepts the stacktrace and the three function template arguments. It contains the __try/__except logic. It calls a new filter_() wrapper template, which calls fill_stacktrace() before forwarding the call to the caller's filter function. fill_stacktrace(), in the .cpp file, contains the logic to populate the stacktrace string -- unless the Structured Exception is stack overflow, in which case it puts an explanatory string instead. catcher_inner()'s __except clause passes not only the code, but also the stacktrace string, to the caller's handler function. It wraps the caller's handler function in always_return<rtype>(), where rtype is the type returned by the trycode function. This allows a handler to return a value, while also supporting the void handler case, e.g. one that throws a C++ exception. (This is why we need AlwaysReturn<void>: some trycode() functions are themselves void.) For the dyadic catcher() overload, introduce common_filter() containing the logic to distinguish a C++ exception from any other kind of Structured Exception. The fact that the stacktrace is captured before the filter function is called should permit capturing a stacktrace for a C++ exception as well as for most other Structured Exceptions. As before, the monadic catcher() overload supplies the rethrow() handler, in the .cpp file. Change existing calls from seh_catcher() to LL::seh::catcher().
Diffstat (limited to 'indra/llcommon/llexception.cpp')
-rw-r--r--indra/llcommon/llexception.cpp24
1 files changed, 8 insertions, 16 deletions
diff --git a/indra/llcommon/llexception.cpp b/indra/llcommon/llexception.cpp
index 74b33f1e3b..107fdc2b2d 100644
--- a/indra/llcommon/llexception.cpp
+++ b/indra/llcommon/llexception.cpp
@@ -101,44 +101,36 @@ void annotate_exception_(boost::exception& exc)
static constexpr U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
static constexpr U32 STATUS_STACK_FULL = 0xC00000FD;
-U32 ll_seh_filter(
- std::string& stacktrace,
- std::function<U32(U32, struct _EXCEPTION_POINTERS*)> filter,
- U32 code,
- struct _EXCEPTION_POINTERS* exception_infop)
+void LL::seh::fill_stacktrace(std::string& stacktrace, U32 code)
{
- // By the time the handler gets control, the stack has been unwound,
- // so report the stack trace now at filter() time.
- // Even though stack overflow is a problem we would very much like to
- // diagnose, calling another function when the stack is already blown only
- // terminates us faster.
+ // Sadly, despite its diagnostic importance, trying to capture a
+ // stacktrace when the stack is already blown only terminates us faster.
if (code == STATUS_STACK_FULL)
{
stacktrace = "(stack overflow, no traceback)";
}
else
{
- stacktrace = boost::stacktrace::stacktrace().to_string();
+ stacktrace = to_string(boost::stacktrace::stacktrace());
}
-
- return filter(code, exception_infop);
}
-U32 seh_filter(U32 code, struct _EXCEPTION_POINTERS*)
+U32 LL::seh::common_filter(U32 code, struct _EXCEPTION_POINTERS*)
{
if (code == STATUS_MSC_EXCEPTION)
{
- // C++ exception, go on
+ // C++ exception, don't stop at this handler
return EXCEPTION_CONTINUE_SEARCH;
}
else
{
// This is a non-C++ exception, e.g. hardware check.
+ // Pass control into the handler block.
return EXCEPTION_EXECUTE_HANDLER;
}
}
-void seh_rethrow(U32 code, const std::string& stacktrace)
+void LL::seh::rethrow(U32 code, const std::string& stacktrace)
{
std::ostringstream out;
out << "Windows exception 0x" << std::hex << code;