summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Kundiman <erik@megapahit.org>2025-06-03 16:21:58 +0800
committerErik Kundiman <erik@megapahit.org>2025-06-03 16:21:58 +0800
commitbbe51e86249114cac4716c391e267c499a52847a (patch)
treed0d71e71163aded7ad93eb026163e0c28729249d
parent9bae19198fdc7bfb71f900cfe6c1982cb2a80e4f (diff)
Revert "Promote seh_catcher() et al. to llexception.{h,cpp} for general use."
This reverts commit 71d777ea126e7f02cb46c11bdb606094ca06f75c.
-rw-r--r--indra/llcommon/llexception.cpp50
-rw-r--r--indra/llcommon/llexception.h86
-rw-r--r--indra/llwindow/llwindowwin32.cpp13
-rw-r--r--indra/newview/llappviewerwin32.cpp36
-rw-r--r--indra/test/test.cpp68
5 files changed, 121 insertions, 132 deletions
diff --git a/indra/llcommon/llexception.cpp b/indra/llcommon/llexception.cpp
index 74b33f1e3b..c0154a569f 100644
--- a/indra/llcommon/llexception.cpp
+++ b/indra/llcommon/llexception.cpp
@@ -15,12 +15,7 @@
#include "llexception.h"
// STL headers
// std headers
-#include <iomanip>
-#include <sstream>
#include <typeinfo>
-#if LL_WINDOWS
-#include <excpt.h>
-#endif // LL_WINDOWS
// external library headers
#include <boost/exception/diagnostic_information.hpp>
#include <boost/exception/error_info.hpp>
@@ -34,6 +29,7 @@
// On Windows, header-only implementation causes macro collisions -- use
// prebuilt library
#define BOOST_STACKTRACE_LINK
+#include <excpt.h>
#endif // LL_WINDOWS
#include <boost/stacktrace.hpp>
@@ -98,34 +94,15 @@ void annotate_exception_(boost::exception& exc)
// For windows SEH exception handling we sometimes need a filter that will
// separate C++ exceptions from C SEH exceptions
-static constexpr U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
-static constexpr U32 STATUS_STACK_FULL = 0xC00000FD;
+static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
-U32 ll_seh_filter(
- std::string& stacktrace,
- std::function<U32(U32, struct _EXCEPTION_POINTERS*)> filter,
- U32 code,
- struct _EXCEPTION_POINTERS* exception_infop)
+U32 msc_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
{
- // 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 = boost::stacktrace::stacktrace().to_string();
- }
-
- return filter(code, exception_infop);
-}
+ const auto stack = to_string(boost::stacktrace::stacktrace());
+ LL_WARNS() << "SEH Exception handled (that probably shouldn't be): Code " << code
+ << "\n Stack trace: \n"
+ << stack << LL_ENDL;
-U32 seh_filter(U32 code, struct _EXCEPTION_POINTERS*)
-{
if (code == STATUS_MSC_EXCEPTION)
{
// C++ exception, go on
@@ -133,20 +110,9 @@ U32 seh_filter(U32 code, struct _EXCEPTION_POINTERS*)
}
else
{
- // This is a non-C++ exception, e.g. hardware check.
+ // handle it
return EXCEPTION_EXECUTE_HANDLER;
}
}
-void seh_rethrow(U32 code, const std::string& stacktrace)
-{
- std::ostringstream out;
- out << "Windows exception 0x" << std::hex << code;
- if (! stacktrace.empty())
- {
- out << '\n' << stacktrace;
- }
- LLTHROW(Windows_SEH_exception(out.str()));
-}
-
#endif //LL_WINDOWS
diff --git a/indra/llcommon/llexception.h b/indra/llcommon/llexception.h
index 3e50678b44..68e609444e 100644
--- a/indra/llcommon/llexception.h
+++ b/indra/llcommon/llexception.h
@@ -102,94 +102,14 @@ 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));
-}
-// 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);
-}
+#if LL_WINDOWS
// 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 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)();
-}
+U32 msc_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop);
-#endif // not LL_WINDOWS -----------------------------------------------------
+#endif //LL_WINDOWS
#endif /* ! defined(LL_LLEXCEPTION_H) */
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 97bd789134..4fca74497f 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -160,7 +160,18 @@ HGLRC SafeCreateContext(HDC &hdc)
GLuint SafeChoosePixelFormat(HDC &hdc, const PIXELFORMATDESCRIPTOR *ppfd)
{
- return seh_catcher(ChoosePixelFormat(hdc, ppfd));
+ __try
+ {
+ return ChoosePixelFormat(hdc, ppfd);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ // convert to C++ styled exception
+ // C exception don't allow classes, so it's a regular char array
+ char integer_string[32];
+ sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
+ throw std::exception(integer_string);
+ }
}
//static
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index ef609026ad..4f5fa53312 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -396,10 +396,17 @@ void ll_nvapi_init(NvDRSSessionHandle hSession)
}
}
-int APIENTRY wWinMain(HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- PWSTR pCmdLine,
- int nCmdShow)
+//#define DEBUGGING_SEH_FILTER 1
+#if DEBUGGING_SEH_FILTER
+# define WINMAIN DebuggingWinMain
+#else
+# define WINMAIN wWinMain
+#endif
+
+int APIENTRY WINMAIN(HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ PWSTR pCmdLine,
+ int nCmdShow)
{
// Call Tracy first thing to have it allocate memory
// https://github.com/wolfpld/tracy/issues/196
@@ -548,6 +555,27 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
return 0;
}
+#if DEBUGGING_SEH_FILTER
+// The compiler doesn't like it when you use __try/__except blocks
+// in a method that uses object destructors. Go figure.
+// This winmain just calls the real winmain inside __try.
+// The __except calls our exception filter function. For debugging purposes.
+int APIENTRY wWinMain(HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ PWSTR lpCmdLine,
+ int nCmdShow)
+{
+ __try
+ {
+ WINMAIN(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
+ }
+ __except( viewer_windows_exception_handler( GetExceptionInformation() ) )
+ {
+ _tprintf( _T("Exception handled.\n") );
+ }
+}
+#endif
+
void LLAppViewerWin32::disableWinErrorReporting()
{
std::string executable_name = gDirUtilp->getExecutableFilename();
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 536c252d97..09147a65a3 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -36,7 +36,6 @@
#include "linden_common.h"
#include "llerrorcontrol.h"
-#include "llexception.h"
#include "lltut.h"
#include "chained_callback.h"
#include "stringize.h"
@@ -57,6 +56,13 @@
#include <boost/iostreams/tee.hpp>
#include <boost/iostreams/stream.hpp>
+// On Mac, got:
+// #error "Boost.Stacktrace requires `_Unwind_Backtrace` function. Define
+// `_GNU_SOURCE` macro or `BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED` if
+// _Unwind_Backtrace is available without `_GNU_SOURCE`."
+#define BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED
+#include <boost/stacktrace.hpp>
+
#include <fstream>
void wouldHaveCrashed(const std::string& message);
@@ -506,6 +512,64 @@ void wouldHaveCrashed(const std::string& message)
static LLTrace::ThreadRecorder* sMasterThreadRecorder = NULL;
+// 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
+
+static constexpr U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
+static constexpr U32 STATUS_STACK_FULL = 0xC00000FD;
+
+U32 seh_filter(U32 code, struct _EXCEPTION_POINTERS*)
+{
+ if (code == STATUS_MSC_EXCEPTION)
+ {
+ // C++ exception, go on -- but TUT is supposed to have caught those already?!
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ else
+ {
+ // This is a non-C++ exception, e.g. hardware check.
+ // By the time the handler gets control, the stack has been unwound,
+ // so report the stack trace now at filter() time.
+ // Sadly, even though, at the time of this writing, stack overflow is
+ // the problem we would most like to diagnose, calling another
+ // function when the stack is already blown only terminates us faster.
+ if (code != STATUS_STACK_FULL)
+ {
+ std::cerr << boost::stacktrace::stacktrace() << std::endl;
+ }
+ // pass control into the handler block
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+}
+
+template <typename CALLABLE0, typename CALLABLE1>
+void seh_catcher(CALLABLE0&& trycode, CALLABLE1&& handler)
+{
+ __try
+ {
+ trycode();
+ }
+ __except (seh_filter(GetExceptionCode(), GetExceptionInformation()))
+ {
+ handler(GetExceptionCode());
+ }
+}
+
+#else // not LL_WINDOWS
+
+template <typename CALLABLE0, typename CALLABLE1>
+void seh_catcher(CALLABLE0&& trycode, CALLABLE1&&)
+{
+ trycode();
+}
+
+#endif // not LL_WINDOWS
+
int main(int argc, char **argv)
{
ll_init_apr();
@@ -652,7 +716,7 @@ int main(int argc, char **argv)
}
},
// __except
- [mycallback](U32 code, const std::string& /*stacktrace*/)
+ [mycallback](U32 code)
{
static std::map<U32, const char*> codes = {
{ 0xC0000005, "Access Violation" },