mirror of
https://github.com/google/googletest.git
synced 2024-12-27 10:11:03 +08:00
Make GoogleTest handle SEH exceptions before stack unwinding rather than afterward
This ensure the erroring stack frame is visible and accessible when the handler is invoked. Fixes #4298 PiperOrigin-RevId: 544692549 Change-Id: Ia165a8c293e8edc820da5f5ad4416546fffe2493
This commit is contained in:
parent
251e720391
commit
1f531be3a1
@ -387,10 +387,10 @@ class GTEST_API_ UnitTestOptions {
|
|||||||
#ifdef GTEST_OS_WINDOWS
|
#ifdef GTEST_OS_WINDOWS
|
||||||
// Function for supporting the gtest_catch_exception flag.
|
// Function for supporting the gtest_catch_exception flag.
|
||||||
|
|
||||||
// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
|
// Returns EXCEPTION_EXECUTE_HANDLER if given SEH exception was handled, or
|
||||||
// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
|
// EXCEPTION_CONTINUE_SEARCH otherwise.
|
||||||
// This function is useful as an __except condition.
|
// This function is useful as an __except condition.
|
||||||
static int GTestShouldProcessSEH(DWORD exception_code);
|
static int GTestProcessSEH(DWORD seh_code, const char* location);
|
||||||
#endif // GTEST_OS_WINDOWS
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
// Returns true if "name" matches the ':' separated list of glob-style
|
// Returns true if "name" matches the ':' separated list of glob-style
|
||||||
|
@ -863,13 +863,18 @@ bool UnitTestOptions::FilterMatchesTest(const std::string& test_suite_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if GTEST_HAS_SEH
|
#if GTEST_HAS_SEH
|
||||||
// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
|
static std::string FormatSehExceptionMessage(DWORD exception_code,
|
||||||
// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
|
const char* location) {
|
||||||
// This function is useful as an __except condition.
|
Message message;
|
||||||
int UnitTestOptions::GTestShouldProcessSEH(DWORD seh_code) {
|
message << "SEH exception with code 0x" << std::setbase(16) << exception_code
|
||||||
|
<< std::setbase(10) << " thrown in " << location << ".";
|
||||||
|
return message.GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
int UnitTestOptions::GTestProcessSEH(DWORD seh_code, const char* location) {
|
||||||
// Google Test should handle a SEH exception if:
|
// Google Test should handle a SEH exception if:
|
||||||
// 1. the user wants it to, AND
|
// 1. the user wants it to, AND
|
||||||
// 2. this is not a breakpoint exception, AND
|
// 2. this is not a breakpoint exception or stack overflow, AND
|
||||||
// 3. this is not a C++ exception (VC++ implements them via SEH,
|
// 3. this is not a C++ exception (VC++ implements them via SEH,
|
||||||
// apparently).
|
// apparently).
|
||||||
//
|
//
|
||||||
@ -877,18 +882,20 @@ int UnitTestOptions::GTestShouldProcessSEH(DWORD seh_code) {
|
|||||||
// (see http://support.microsoft.com/kb/185294 for more information).
|
// (see http://support.microsoft.com/kb/185294 for more information).
|
||||||
const DWORD kCxxExceptionCode = 0xe06d7363;
|
const DWORD kCxxExceptionCode = 0xe06d7363;
|
||||||
|
|
||||||
bool should_handle = true;
|
if (!GTEST_FLAG_GET(catch_exceptions) || seh_code == kCxxExceptionCode ||
|
||||||
|
seh_code == EXCEPTION_BREAKPOINT ||
|
||||||
|
seh_code == EXCEPTION_STACK_OVERFLOW) {
|
||||||
|
return EXCEPTION_CONTINUE_SEARCH; // Don't handle these exceptions
|
||||||
|
}
|
||||||
|
|
||||||
if (!GTEST_FLAG_GET(catch_exceptions))
|
internal::ReportFailureInUnknownLocation(
|
||||||
should_handle = false;
|
TestPartResult::kFatalFailure,
|
||||||
else if (seh_code == EXCEPTION_BREAKPOINT)
|
FormatSehExceptionMessage(seh_code, location) +
|
||||||
should_handle = false;
|
"\n"
|
||||||
else if (seh_code == EXCEPTION_STACK_OVERFLOW)
|
"Stack trace:\n" +
|
||||||
should_handle = false;
|
::testing::internal::GetCurrentOsStackTraceExceptTop(1));
|
||||||
else if (seh_code == kCxxExceptionCode)
|
|
||||||
should_handle = false;
|
|
||||||
|
|
||||||
return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
|
return EXCEPTION_EXECUTE_HANDLER;
|
||||||
}
|
}
|
||||||
#endif // GTEST_HAS_SEH
|
#endif // GTEST_HAS_SEH
|
||||||
|
|
||||||
@ -2555,18 +2562,6 @@ bool Test::HasSameFixtureClass() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GTEST_HAS_SEH
|
|
||||||
|
|
||||||
static std::string FormatSehExceptionMessage(DWORD exception_code,
|
|
||||||
const char* location) {
|
|
||||||
Message message;
|
|
||||||
message << "SEH exception with code 0x" << std::setbase(16) << exception_code
|
|
||||||
<< std::setbase(10) << " thrown in " << location << ".";
|
|
||||||
return message.GetString();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // GTEST_HAS_SEH
|
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
#if GTEST_HAS_EXCEPTIONS
|
#if GTEST_HAS_EXCEPTIONS
|
||||||
@ -2608,22 +2603,8 @@ Result HandleSehExceptionsInMethodIfSupported(T* object, Result (T::*method)(),
|
|||||||
#if GTEST_HAS_SEH
|
#if GTEST_HAS_SEH
|
||||||
__try {
|
__try {
|
||||||
return (object->*method)();
|
return (object->*method)();
|
||||||
} __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT
|
} __except (internal::UnitTestOptions::GTestProcessSEH( // NOLINT
|
||||||
GetExceptionCode())) {
|
GetExceptionCode(), location)) {
|
||||||
// We wrap an inner function because VC++ prohibits direct creation of
|
|
||||||
// objects with destructors on stack in functions using __try
|
|
||||||
// (see error C2712).
|
|
||||||
struct Wrapper {
|
|
||||||
static void ReportFailure(DWORD code, const char* location) {
|
|
||||||
return internal::ReportFailureInUnknownLocation(
|
|
||||||
TestPartResult::kFatalFailure,
|
|
||||||
FormatSehExceptionMessage(code, location) +
|
|
||||||
"\n"
|
|
||||||
"Stack trace:\n" +
|
|
||||||
::testing::internal::GetCurrentOsStackTraceExceptTop(1));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Wrapper::ReportFailure(GetExceptionCode(), location);
|
|
||||||
return static_cast<Result>(0);
|
return static_cast<Result>(0);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user