mirror of
https://github.com/bkaradzic/bx.git
synced 2026-06-08 03:03:48 +00:00
Suppress MSVC CRT assert dialogs. (#395)
This commit is contained in:
committed by
GitHub
parent
217823bc0a
commit
eed706fb27
120
src/debug.cpp
120
src/debug.cpp
@@ -65,6 +65,12 @@
|
|||||||
# include <signal.h>
|
# include <signal.h>
|
||||||
#endif // BX_CONFIG_EXCEPTION_HANDLING_*
|
#endif // BX_CONFIG_EXCEPTION_HANDLING_*
|
||||||
|
|
||||||
|
#if BX_CONFIG_EXCEPTION_HANDLING_USE_WINDOWS_SEH && BX_CRT_MSVC
|
||||||
|
# include <stdlib.h> // _set_abort_behavior, _set_invalid_parameter_handler, _set_purecall_handler
|
||||||
|
# include <crtdbg.h> // _CrtSetReportMode, _CrtSetReportHook
|
||||||
|
extern "C" __declspec(dllimport) unsigned int __stdcall SetErrorMode(unsigned int uMode);
|
||||||
|
#endif // BX_CONFIG_EXCEPTION_HANDLING_USE_WINDOWS_SEH && BX_CRT_MSVC
|
||||||
|
|
||||||
#if BX_CRT_NONE
|
#if BX_CRT_NONE
|
||||||
# include <bx/crt0.h>
|
# include <bx/crt0.h>
|
||||||
#elif BX_PLATFORM_ANDROID
|
#elif BX_PLATFORM_ANDROID
|
||||||
@@ -1304,6 +1310,96 @@ namespace bx
|
|||||||
typedef uint32_t (__stdcall* TopLevelExceptionFilterFn)(ExceptionPointers* _exceptionInfo);
|
typedef uint32_t (__stdcall* TopLevelExceptionFilterFn)(ExceptionPointers* _exceptionInfo);
|
||||||
typedef TopLevelExceptionFilterFn (__stdcall* SetUnhandledExceptionFilterFn)(TopLevelExceptionFilterFn _topLevelExceptionFilter);
|
typedef TopLevelExceptionFilterFn (__stdcall* SetUnhandledExceptionFilterFn)(TopLevelExceptionFilterFn _topLevelExceptionFilter);
|
||||||
|
|
||||||
|
#if BX_CRT_MSVC
|
||||||
|
template<uint16_t MaxCapacityT>
|
||||||
|
static void wcharToNarrow(FixedStringT<MaxCapacityT>& _dst, const wchar_t* _src)
|
||||||
|
{
|
||||||
|
if (NULL == _src)
|
||||||
|
{
|
||||||
|
_dst.set("<unknown>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
typename FixedStringT<MaxCapacityT>::Pod& pod = _dst.asPod();
|
||||||
|
const uint32_t last = MaxCapacityT - 1;
|
||||||
|
uint32_t ii = 0;
|
||||||
|
for (; ii < last && _src[ii] != L'\0'; ++ii)
|
||||||
|
{
|
||||||
|
const wchar_t wc = _src[ii];
|
||||||
|
pod.storage[ii] = (wc >= 0x20 && wc < 0x7f) ? char(wc) : '?';
|
||||||
|
}
|
||||||
|
pod.storage[ii] = '\0';
|
||||||
|
pod.len = int32_t(ii);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void invalidParameterHandler(const wchar_t* _expression, const wchar_t* _function, const wchar_t* _file, unsigned int _line, uintptr_t /*_reserved*/)
|
||||||
|
{
|
||||||
|
FixedString256 expression;
|
||||||
|
FixedString256 function;
|
||||||
|
FixedString1024 file;
|
||||||
|
wcharToNarrow(expression, _expression);
|
||||||
|
wcharToNarrow(function, _function);
|
||||||
|
wcharToNarrow(file, _file);
|
||||||
|
|
||||||
|
const StringView svExpression = expression;
|
||||||
|
const StringView svFunction = function;
|
||||||
|
const StringView svFile = file;
|
||||||
|
|
||||||
|
if (assertFunction(
|
||||||
|
Location("MSVC CRT Debug Error", UINT32_MAX)
|
||||||
|
, 3
|
||||||
|
, "CRT Invalid parameter: %S (%S:%u) %S"
|
||||||
|
, &svFunction
|
||||||
|
, &svFile
|
||||||
|
, _line
|
||||||
|
, &svExpression
|
||||||
|
) )
|
||||||
|
{
|
||||||
|
exit(kExitFailure, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pureCallHandler()
|
||||||
|
{
|
||||||
|
if (assertFunction(Location("Exception Handler", UINT32_MAX), 1, "CRT Pure virtual function call.") )
|
||||||
|
{
|
||||||
|
exit(kExitFailure, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# if BX_CONFIG_DEBUG
|
||||||
|
static int __cdecl crtReportHook(int _reportType, char* _message, int* _returnValue)
|
||||||
|
{
|
||||||
|
const char* type = "Report";
|
||||||
|
switch (_reportType)
|
||||||
|
{
|
||||||
|
case 0 /*_CRT_WARN */: type = "Warning"; break;
|
||||||
|
case 1 /*_CRT_ERROR */: type = "Error"; break;
|
||||||
|
case 2 /*_CRT_ASSERT*/: type = "Assert"; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (assertFunction(
|
||||||
|
Location("MSVC CRT Debug Error", UINT32_MAX)
|
||||||
|
, 3
|
||||||
|
, "CRT %s: %s"
|
||||||
|
, type
|
||||||
|
, NULL != _message ? _message : "<unknown>"
|
||||||
|
) )
|
||||||
|
{
|
||||||
|
exit(kExitFailure, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL != _returnValue)
|
||||||
|
{
|
||||||
|
*_returnValue = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1 /* TRUE: report handled, suppress dialog */;
|
||||||
|
}
|
||||||
|
# endif // BX_CONFIG_DEBUG
|
||||||
|
#endif // BX_CRT_MSVC
|
||||||
|
|
||||||
struct ExceptionHandler
|
struct ExceptionHandler
|
||||||
{
|
{
|
||||||
ExceptionHandler()
|
ExceptionHandler()
|
||||||
@@ -1322,6 +1418,30 @@ namespace bx
|
|||||||
|
|
||||||
bx::dlclose(kernel32Dll);
|
bx::dlclose(kernel32Dll);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if BX_CRT_MSVC
|
||||||
|
// Suppress Windows error mode dialogs ("application has stopped working").
|
||||||
|
SetErrorMode(0
|
||||||
|
| 0x0001 /* SEM_FAILCRITICALERRORS */
|
||||||
|
| 0x0002 /* SEM_NOGPFAULTERRORBOX */
|
||||||
|
);
|
||||||
|
|
||||||
|
// Suppress the "abort() has been called" message box and Windows Error Reporting.
|
||||||
|
_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
|
||||||
|
|
||||||
|
// Route CRT invalid parameter and pure virtual call into bx assert handler.
|
||||||
|
_set_invalid_parameter_handler(invalidParameterHandler);
|
||||||
|
_set_thread_local_invalid_parameter_handler(invalidParameterHandler);
|
||||||
|
_set_purecall_handler(pureCallHandler);
|
||||||
|
|
||||||
|
# if BX_CONFIG_DEBUG
|
||||||
|
// Route _CrtDbgReport "Debug Error!" dialogs through bx assert handler.
|
||||||
|
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
|
||||||
|
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
|
||||||
|
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
|
||||||
|
_CrtSetReportHook(crtReportHook);
|
||||||
|
# endif // BX_CONFIG_DEBUG
|
||||||
|
#endif // BX_CRT_MSVC
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t __stdcall topLevelExceptionFilter(ExceptionPointers* _info)
|
static uint32_t __stdcall topLevelExceptionFilter(ExceptionPointers* _info)
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ int runAllTests(int32_t _argc, const char* _argv[])
|
|||||||
ConfigData config;
|
ConfigData config;
|
||||||
config.defaultColourMode = BX_PLATFORM_EMSCRIPTEN
|
config.defaultColourMode = BX_PLATFORM_EMSCRIPTEN
|
||||||
? ColourMode::None
|
? ColourMode::None
|
||||||
: ColourMode::PlatformDefault
|
: ColourMode::PlatformDefault
|
||||||
;
|
;
|
||||||
config.showDurations = ShowDurations::Always;
|
config.showDurations = ShowDurations::Always;
|
||||||
|
|
||||||
|
|||||||
28
tests/test.h
28
tests/test.h
@@ -11,20 +11,26 @@
|
|||||||
// Override bx asserts in test builds: failing asserts throw std::exception so that Catch2's
|
// Override bx asserts in test builds: failing asserts throw std::exception so that Catch2's
|
||||||
// REQUIRE_ASSERTS (REQUIRE_THROWS) can catch them.
|
// REQUIRE_ASSERTS (REQUIRE_THROWS) can catch them.
|
||||||
#if BX_CONFIG_DEBUG
|
#if BX_CONFIG_DEBUG
|
||||||
# define BX_ASSERT(_condition, ...) \
|
# define BX_ASSERT(_condition, ...) \
|
||||||
do { \
|
do { \
|
||||||
if (!(_condition) ) \
|
if (!(_condition) ) \
|
||||||
{ \
|
{ \
|
||||||
throw ::std::exception(); \
|
BX_PRAGMA_DIAGNOSTIC_PUSH(); \
|
||||||
} \
|
BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4297); \
|
||||||
|
throw ::std::exception(); \
|
||||||
|
BX_PRAGMA_DIAGNOSTIC_POP(); \
|
||||||
|
} \
|
||||||
} while (false)
|
} while (false)
|
||||||
|
|
||||||
# define BX_ASSERT_LOC(_location, _condition, ...) \
|
# define BX_ASSERT_LOC(_location, _condition, ...) \
|
||||||
do { \
|
do { \
|
||||||
(void)(_location); \
|
(void)(_location); \
|
||||||
if (!(_condition) ) \
|
if (!(_condition) ) \
|
||||||
{ \
|
{ \
|
||||||
throw ::std::exception(); \
|
BX_PRAGMA_DIAGNOSTIC_PUSH(); \
|
||||||
|
BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4297); \
|
||||||
|
throw ::std::exception(); \
|
||||||
|
BX_PRAGMA_DIAGNOSTIC_POP(); \
|
||||||
} \
|
} \
|
||||||
} while (false)
|
} while (false)
|
||||||
#endif // BX_CONFIG_DEBUG
|
#endif // BX_CONFIG_DEBUG
|
||||||
|
|||||||
Reference in New Issue
Block a user