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.h104
1 files changed, 41 insertions, 63 deletions
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) */