summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llcommon/always_return.h16
-rw-r--r--indra/llcommon/llexception.cpp24
-rw-r--r--indra/llcommon/llexception.h104
-rw-r--r--indra/llwindow/llwindowwin32.cpp2
-rw-r--r--indra/test/test.cpp2
5 files changed, 59 insertions, 89 deletions
diff --git a/indra/llcommon/always_return.h b/indra/llcommon/always_return.h
index b99eb49096..a206471da5 100644
--- a/indra/llcommon/always_return.h
+++ b/indra/llcommon/always_return.h
@@ -79,22 +79,6 @@ namespace LL
DESIRED mDefault;
};
- // specialize for AlwaysReturn<void>
- template <>
- struct AlwaysReturn<void>
- {
- public:
- AlwaysReturn() {}
-
- // callable returns a type not convertible to DESIRED, return default
- template <typename CALLABLE, typename... ARGS>
- void operator()(CALLABLE&& callable, ARGS&&... args)
- {
- // discard whatever callable(args) returns
- std::forward<CALLABLE>(callable)(std::forward<ARGS>(args)...);
- }
- };
-
/**
* always_return<T>(some_function, some_args...) calls
* some_function(some_args...). It is guaranteed to return a value of type
diff --git a/indra/llcommon/llexception.cpp b/indra/llcommon/llexception.cpp
index 107fdc2b2d..74b33f1e3b 100644
--- a/indra/llcommon/llexception.cpp
+++ b/indra/llcommon/llexception.cpp
@@ -101,36 +101,44 @@ void annotate_exception_(boost::exception& exc)
static constexpr U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
static constexpr U32 STATUS_STACK_FULL = 0xC00000FD;
-void LL::seh::fill_stacktrace(std::string& stacktrace, U32 code)
+U32 ll_seh_filter(
+ std::string& stacktrace,
+ std::function<U32(U32, struct _EXCEPTION_POINTERS*)> filter,
+ U32 code,
+ struct _EXCEPTION_POINTERS* exception_infop)
{
- // Sadly, despite its diagnostic importance, trying to capture a
- // stacktrace when the stack is already blown only terminates us faster.
+ // 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.
if (code == STATUS_STACK_FULL)
{
stacktrace = "(stack overflow, no traceback)";
}
else
{
- stacktrace = to_string(boost::stacktrace::stacktrace());
+ stacktrace = boost::stacktrace::stacktrace().to_string();
}
+
+ return filter(code, exception_infop);
}
-U32 LL::seh::common_filter(U32 code, struct _EXCEPTION_POINTERS*)
+U32 seh_filter(U32 code, struct _EXCEPTION_POINTERS*)
{
if (code == STATUS_MSC_EXCEPTION)
{
- // C++ exception, don't stop at this handler
+ // C++ exception, go on
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 LL::seh::rethrow(U32 code, const std::string& stacktrace)
+void seh_rethrow(U32 code, const std::string& stacktrace)
{
std::ostringstream out;
out << "Windows exception 0x" << std::hex << code;
diff --git a/indra/llcommon/llexception.h b/indra/llcommon/llexception.h
index f58a553eb3..3e50678b44 100644
--- a/indra/llcommon/llexception.h
+++ b/indra/llcommon/llexception.h
@@ -12,7 +12,6 @@
#if ! defined(LL_LLEXCEPTION_H)
#define LL_LLEXCEPTION_H
-#include "always_return.h"
#include <stdexcept>
#include <boost/exception/exception.hpp>
#include <boost/throw_exception.hpp>
@@ -107,111 +106,90 @@ void log_unhandled_exception_(const char*, int, const char*, const std::string&)
* Structured Exception Handling
*****************************************************************************/
// this is used in platform-generic code -- define outside #if LL_WINDOWS
-struct Windows_SEH_exception: public LLException
+struct Windows_SEH_exception: public std::runtime_error
{
- Windows_SEH_exception(const std::string& what): LLException(what) {}
+ Windows_SEH_exception(const std::string& what): std::runtime_error(what) {}
};
-namespace LL
-{
-namespace seh
-{
-
#if LL_WINDOWS //-------------------------------------------------------------
-void fill_stacktrace(std::string& stacktrace, U32 code);
-
-// wrapper around caller's U32 filter(U32 code, struct _EXCEPTION_POINTERS*)
-// filter function: capture a stacktrace, if possible, before forwarding the
-// call to the caller's filter() function
-template <typename FILTER>
-U32 filter_(std::string& stacktrace, FILTER&& filter,
- U32 code, struct _EXCEPTION_POINTERS* exptrs)
-{
- // By the time the handler gets control, the stack has been unwound,
- // so report the stack trace now at filter() time.
- fill_stacktrace(stacktrace, code);
- return std::forward<FILTER>(filter)(code, exptrs);
-}
+#include <functional>
+// triadic variant specifies try(), filter(U32, struct _EXCEPTION_POINTERS*),
+// handler(U32, const std::string& stacktrace)
+// stacktrace may or may not be available
template <typename TRYCODE, typename FILTER, typename HANDLER>
-auto catcher_inner(std::string& stacktrace,
- TRYCODE&& trycode, FILTER&& filter, HANDLER&& handler)
+auto seh_catcher(TRYCODE&& trycode, FILTER&& filter, HANDLER&& handler)
{
+ // don't try to construct a std::function at the moment of Structured Exception
+ std::function<U32(U32, struct _EXCEPTION_POINTERS*)>
+ filter_function(std::forward<FILTER>(filter));
+ std::string stacktrace;
__try
{
return std::forward<TRYCODE>(trycode)();
}
- __except (filter_(stacktrace,
- std::forward<FILTER>(filter),
- GetExceptionCode(), GetExceptionInformation()))
+ __except (ll_seh_filter(
+ stacktrace,
+ filter_function,
+ GetExceptionCode(),
+ GetExceptionInformation()))
{
- return always_return<decltype(trycode())>(
- std::forward<HANDLER>(handler), GetExceptionCode(), stacktrace);
+ return std::forward<HANDLER>(handler)(GetExceptionCode(), stacktrace);
}
}
-// triadic variant specifies try(), filter(U32, struct _EXCEPTION_POINTERS*),
-// handler(U32, const std::string& stacktrace)
-// stacktrace may or may not be available
-template <typename TRYCODE, typename FILTER, typename HANDLER>
-auto catcher(TRYCODE&& trycode, FILTER&& filter, HANDLER&& handler)
-{
- // Construct and destroy this stacktrace string in the outer function
- // because we can't do either in the function with __try/__except.
- std::string stacktrace;
- return catcher_inner(stacktrace,
- std::forward<TRYCODE>(trycode),
- std::forward<FILTER>(filter),
- std::forward<HANDLER>(handler));
-}
-
-// common_filter() handles the typical case in which we want our handler
-// clause to handle only Structured Exceptions rather than explicitly-thrown
-// C++ exceptions
-U32 common_filter(U32 code, struct _EXCEPTION_POINTERS*);
-
-// dyadic variant specifies try(), handler(U32, stacktrace), assumes common_filter()
+// dyadic variant specifies try(), handler(U32, stacktrace), assumes default filter
template <typename TRYCODE, typename HANDLER>
-auto catcher(TRYCODE&& trycode, HANDLER&& handler)
+auto seh_catcher(TRYCODE&& trycode, HANDLER&& handler)
{
- return catcher(std::forward<TRYCODE>(trycode),
- common_filter,
- std::forward<HANDLER>(handler));
+ return seh_catcher(
+ std::forward<TRYCODE>(trycode),
+ seh_filter,
+ std::forward<HANDLER>(handler));
}
// monadic variant specifies try(), assumes default filter and handler
template <typename TRYCODE>
-auto catcher(TRYCODE&& trycode)
+auto seh_catcher(TRYCODE&& trycode)
{
- return catcher(std::forward<TRYCODE>(trycode), rethrow);
+ return seh_catcher(
+ std::forward<TRYCODE>(trycode),
+ seh_filter,
+ seh_rethrow);
}
-[[noreturn]] void rethrow(U32 code, const std::string& stacktrace);
+// SEH exception filtering for use in __try __except
+// Separates C++ exceptions from C SEH exceptions
+// Todo: might be good idea to do some kind of seh_to_msc_wrapper(function, ARGS&&);
+U32 ll_seh_filter(
+ std::string& stacktrace,
+ std::function<U32(U32, struct _EXCEPTION_POINTERS*)> filter,
+ U32 code,
+ struct _EXCEPTION_POINTERS* exception_infop);
+U32 seh_filter(U32 code, struct _EXCEPTION_POINTERS* exception_infop);
+void seh_rethrow(U32 code, const std::string& stacktrace);
#else // not LL_WINDOWS -----------------------------------------------------
template <typename TRYCODE, typename FILTER, typename HANDLER>
-auto catcher(TRYCODE&& trycode, FILTER&&, HANDLER&&)
+auto seh_catcher(TRYCODE&& trycode, FILTER&&, HANDLER&&)
{
return std::forward<TRYCODE>(trycode)();
}
template <typename TRYCODE, typename HANDLER>
-auto catcher(TRYCODE&& trycode, HANDLER&&)
+auto seh_catcher(TRYCODE&& trycode, HANDLER&&)
{
return std::forward<TRYCODE>(trycode)();
}
template <typename TRYCODE>
-auto catcher(TRYCODE&& trycode)
+auto seh_catcher(TRYCODE&& trycode)
{
return std::forward<TRYCODE>(trycode)();
}
#endif // not LL_WINDOWS -----------------------------------------------------
-} // namespace LL::seh
-} // namespace LL
-
#endif /* ! defined(LL_LLEXCEPTION_H) */
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index a781e638ee..97bd789134 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -160,7 +160,7 @@ HGLRC SafeCreateContext(HDC &hdc)
GLuint SafeChoosePixelFormat(HDC &hdc, const PIXELFORMATDESCRIPTOR *ppfd)
{
- return LL::seh::catcher([hdc, ppfd]{ return ChoosePixelFormat(hdc, ppfd); });
+ return seh_catcher(ChoosePixelFormat(hdc, ppfd));
}
//static
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 6e280819df..536c252d97 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -638,7 +638,7 @@ int main(int argc, char **argv)
// a chained_callback subclass must be linked with previous
mycallback->link();
- LL::seh::catcher(
+ seh_catcher(
// __try
[test_group]
{