summaryrefslogtreecommitdiff
path: root/indra/llcommon/llexception.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/llexception.h')
-rw-r--r--indra/llcommon/llexception.h86
1 files changed, 83 insertions, 3 deletions
diff --git a/indra/llcommon/llexception.h b/indra/llcommon/llexception.h
index 68e609444e..3e50678b44 100644
--- a/indra/llcommon/llexception.h
+++ b/indra/llcommon/llexception.h
@@ -102,14 +102,94 @@ void crash_on_unhandled_exception_(const char*, int, const char*, const std::str
log_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, CONTEXT)
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 std::runtime_error
+{
+ Windows_SEH_exception(const std::string& what): std::runtime_error(what) {}
+};
+
+#if LL_WINDOWS //-------------------------------------------------------------
+
+#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 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 (ll_seh_filter(
+ stacktrace,
+ filter_function,
+ GetExceptionCode(),
+ GetExceptionInformation()))
+ {
+ return std::forward<HANDLER>(handler)(GetExceptionCode(), stacktrace);
+ }
+}
+
+// dyadic variant specifies try(), handler(U32, stacktrace), assumes default filter
+template <typename TRYCODE, typename HANDLER>
+auto seh_catcher(TRYCODE&& trycode, HANDLER&& handler)
+{
+ return seh_catcher(
+ std::forward<TRYCODE>(trycode),
+ seh_filter,
+ std::forward<HANDLER>(handler));
+}
-#if LL_WINDOWS
+// monadic variant specifies try(), assumes default filter and handler
+template <typename TRYCODE>
+auto seh_catcher(TRYCODE&& trycode)
+{
+ return seh_catcher(
+ std::forward<TRYCODE>(trycode),
+ seh_filter,
+ seh_rethrow);
+}
// 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 msc_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop);
+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 seh_catcher(TRYCODE&& trycode, FILTER&&, HANDLER&&)
+{
+ return std::forward<TRYCODE>(trycode)();
+}
+
+template <typename TRYCODE, typename HANDLER>
+auto seh_catcher(TRYCODE&& trycode, HANDLER&&)
+{
+ return std::forward<TRYCODE>(trycode)();
+}
+
+template <typename TRYCODE>
+auto seh_catcher(TRYCODE&& trycode)
+{
+ return std::forward<TRYCODE>(trycode)();
+}
-#endif //LL_WINDOWS
+#endif // not LL_WINDOWS -----------------------------------------------------
#endif /* ! defined(LL_LLEXCEPTION_H) */