SL-14347 Crash at ChoosePixelFormat SEH

master
Andrey Kleshchev 2020-12-01 18:21:43 +02:00
parent 6d06c8b9de
commit bb4d02446f
5 changed files with 57 additions and 41 deletions

View File

@ -56,10 +56,6 @@
#include "stringize.h"
#include "llexception.h"
#if LL_WINDOWS
#include <excpt.h>
#endif
// static
LLCoros::CoroData& LLCoros::get_CoroData(const std::string& caller)
{
@ -253,29 +249,13 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl
#if LL_WINDOWS
static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
{
if (code == STATUS_MSC_EXCEPTION)
{
// C++ exception, go on
return EXCEPTION_CONTINUE_SEARCH;
}
else
{
// handle it
return EXCEPTION_EXECUTE_HANDLER;
}
}
void LLCoros::winlevel(const callable_t& callable)
{
__try
{
callable();
}
__except (exception_filter(GetExceptionCode(), GetExceptionInformation()))
__except (msc_exception_filter(GetExceptionCode(), GetExceptionInformation()))
{
// convert to C++ styled exception
// Note: it might be better to use _se_set_translator

View File

@ -24,11 +24,14 @@
// `_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
#if LL_WINDOWS
// 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>
// other Linden headers
#include "llerror.h"
@ -85,3 +88,25 @@ void annotate_exception_(boost::exception& exc)
// Anyway, which of us is really going to examine more than 100 frames?
exc << errinfo_stacktrace(boost::stacktrace::stacktrace(1, 100));
}
#if LL_WINDOWS
// For windows SEH exception handling we sometimes need a filter that will
// separate C++ exceptions from C SEH exceptions
static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
U32 msc_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
{
if (code == STATUS_MSC_EXCEPTION)
{
// C++ exception, go on
return EXCEPTION_CONTINUE_SEARCH;
}
else
{
// handle it
return EXCEPTION_EXECUTE_HANDLER;
}
}
#endif //LL_WINDOWS

View File

@ -102,4 +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&);
#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 msc_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop);
#endif //LL_WINDOWS
#endif /* ! defined(LL_LLEXCEPTION_H) */

View File

@ -38,6 +38,7 @@
// Linden library includes
#include "llerror.h"
#include "llexception.h"
#include "llfasttimer.h"
#include "llgl.h"
#include "llstring.h"
@ -117,7 +118,7 @@ void show_window_creation_error(const std::string& title)
LL_WARNS("Window") << title << LL_ENDL;
}
HGLRC SafeCreateContext(HDC hdc)
HGLRC SafeCreateContext(HDC &hdc)
{
__try
{
@ -129,6 +130,22 @@ HGLRC SafeCreateContext(HDC hdc)
}
}
GLuint SafeChoosePixelFormat(HDC &hdc, const PIXELFORMATDESCRIPTOR *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
BOOL LLWindowWin32::sIsClassRegistered = FALSE;
@ -1234,7 +1251,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
try
{
// Looks like ChoosePixelFormat can crash in case of faulty driver
if (!(pixel_format = ChoosePixelFormat(mhDC, &pfd)))
if (!(pixel_format = SafeChoosePixelFormat(mhDC, &pfd)))
{
LL_WARNS("Window") << "ChoosePixelFormat failed, code: " << GetLastError() << LL_ENDL;
OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"),
@ -1245,7 +1262,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
}
catch (...)
{
LL_WARNS("Window") << "ChoosePixelFormat failed." << LL_ENDL;
LOG_UNHANDLED_EXCEPTION("ChoosePixelFormat");
OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"),
mCallbacks->translateString("MBError"), OSMB_OK);
close();

View File

@ -379,22 +379,6 @@ F32 gpu_benchmark();
#if LL_WINDOWS
static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
U32 exception_benchmark_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
{
if (code == STATUS_MSC_EXCEPTION)
{
// C++ exception, go on
return EXCEPTION_CONTINUE_SEARCH;
}
else
{
// handle it
return EXCEPTION_EXECUTE_HANDLER;
}
}
F32 logExceptionBenchmark()
{
// Todo: make a wrapper/class for SEH exceptions
@ -403,7 +387,7 @@ F32 logExceptionBenchmark()
{
gbps = gpu_benchmark();
}
__except (exception_benchmark_filter(GetExceptionCode(), GetExceptionInformation()))
__except (msc_exception_filter(GetExceptionCode(), GetExceptionInformation()))
{
// convert to C++ styled exception
char integer_string[32];