Core/CrashHandler: Include assertion messages in crash reports

(cherry picked from commit 62db1fb683)
This commit is contained in:
Shauren
2018-08-29 23:59:24 +02:00
parent 55cb4f9a6d
commit d181c1da75
4 changed files with 90 additions and 30 deletions

View File

@@ -16,7 +16,7 @@
*/
#include "Errors.h"
#include "StringFormat.h"
#include <cstdio>
#include <cstdlib>
#include <thread>
@@ -33,14 +33,46 @@
terminates the application.
*/
namespace Trinity {
#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
#define Crash(message) \
ULONG_PTR execeptionArgs[] = { reinterpret_cast<ULONG_PTR>(strdup(message)), reinterpret_cast<ULONG_PTR>(_ReturnAddress()) }; \
RaiseException(EXCEPTION_ASSERTION_FAILURE, 0, 2, execeptionArgs);
#else
// should be easily accessible in gdb
extern "C" TC_COMMON_API char const* TrinityAssertionFailedMessage = nullptr;
#define Crash(message) \
TrinityAssertionFailedMessage = strdup(message); \
*((volatile int*)nullptr) = 0; \
exit(1);
#endif
namespace
{
std::string FormatAssertionMessage(char const* format, va_list args)
{
std::string formatted;
va_list len;
va_copy(len, args);
int32 length = vsnprintf(nullptr, 0, format, len);
va_end(len);
formatted.resize(length + 1);
vsnprintf(&formatted[0], length + 1, format, args);
return formatted;
}
}
namespace Trinity
{
void Assert(char const* file, int line, char const* function, char const* message)
{
fprintf(stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s\n",
file, line, function, message);
*((volatile int*)nullptr) = 0;
exit(1);
std::string formattedMessage = StringFormat("\n%s:%i in %s ASSERTION FAILED:\n %s\n", file, line, function, message);
fprintf(stderr, "%s", formattedMessage.c_str());
fflush(stderr);
Crash(formattedMessage.c_str());
}
void Assert(char const* file, int line, char const* function, char const* message, char const* format, ...)
@@ -48,14 +80,13 @@ void Assert(char const* file, int line, char const* function, char const* messag
va_list args;
va_start(args, format);
fprintf(stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s ", file, line, function, message);
vfprintf(stderr, format, args);
fprintf(stderr, "\n");
std::string formattedMessage = StringFormat("\n%s:%i in %s ASSERTION FAILED:\n %s\n", file, line, function, message) + FormatAssertionMessage(format, args) + '\n';
va_end(args);
fprintf(stderr, "%s", formattedMessage.c_str());
fflush(stderr);
va_end(args);
*((volatile int*)nullptr) = 0;
exit(1);
Crash(formattedMessage.c_str());
}
void Fatal(char const* file, int line, char const* function, char const* message, ...)
@@ -63,22 +94,22 @@ void Fatal(char const* file, int line, char const* function, char const* message
va_list args;
va_start(args, message);
fprintf(stderr, "\n%s:%i in %s FATAL ERROR:\n ", file, line, function);
vfprintf(stderr, message, args);
fprintf(stderr, "\n");
std::string formattedMessage = StringFormat("\n%s:%i in %s FATAL ERROR:\n %s\n", file, line, function) + FormatAssertionMessage(message, args) + '\n';
va_end(args);
fprintf(stderr, "%s", formattedMessage.c_str());
fflush(stderr);
std::this_thread::sleep_for(std::chrono::seconds(10));
*((volatile int*)nullptr) = 0;
exit(1);
Crash(formattedMessage.c_str());
}
void Error(char const* file, int line, char const* function, char const* message)
{
fprintf(stderr, "\n%s:%i in %s ERROR:\n %s\n",
file, line, function, message);
*((volatile int*)nullptr) = 0;
exit(1);
std::string formattedMessage = StringFormat("\n%s:%i in %s ERROR:\n %s\n", file, line, function, message);
fprintf(stderr, "%s", formattedMessage.c_str());
fflush(stderr);
Crash(formattedMessage.c_str());
}
void Warning(char const* file, int line, char const* function, char const* message)
@@ -89,17 +120,19 @@ void Warning(char const* file, int line, char const* function, char const* messa
void Abort(char const* file, int line, char const* function)
{
fprintf(stderr, "\n%s:%i in %s ABORTED.\n",
file, line, function);
*((volatile int*)nullptr) = 0;
exit(1);
std::string formattedMessage = StringFormat("\n%s:%i in %s ABORTED.\n", file, line, function);
fprintf(stderr, "%s", formattedMessage.c_str());
fflush(stderr);
Crash(formattedMessage.c_str());
}
void AbortHandler(int /*sigval*/)
void AbortHandler(int sigval)
{
// nothing useful to log here, no way to pass args
*((volatile int*)nullptr) = 0;
exit(1);
std::string formattedMessage = StringFormat("Caught signal %i\n", sigval);
fprintf(stderr, "%s", formattedMessage.c_str());
fflush(stderr);
Crash(formattedMessage.c_str());
}
} // namespace Trinity

View File

@@ -45,6 +45,10 @@ namespace Trinity
#define ASSERT_END
#endif
#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
#define EXCEPTION_ASSERTION_FAILURE 0xC0000420L
#endif
#define WPAssert(cond, ...) ASSERT_BEGIN do { if (!(cond)) Trinity::Assert(__FILE__, __LINE__, __FUNCTION__, #cond, ##__VA_ARGS__); } while(0) ASSERT_END
#define WPFatal(cond, ...) ASSERT_BEGIN do { if (!(cond)) Trinity::Fatal(__FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); } while(0) ASSERT_END
#define WPError(cond, msg) ASSERT_BEGIN do { if (!(cond)) Trinity::Error(__FILE__, __LINE__, __FUNCTION__, (msg)); } while(0) ASSERT_END

View File

@@ -22,6 +22,7 @@
#include "WheatyExceptionReport.h"
#include "Common.h"
#include "Errors.h"
#include "GitRevision.h"
#include <algorithm>
@@ -171,8 +172,21 @@ PEXCEPTION_POINTERS pExceptionInfo)
info.ExceptionPointers = pExceptionInfo;
info.ThreadId = GetCurrentThreadId();
MINIDUMP_USER_STREAM additionalStream = {};
MINIDUMP_USER_STREAM_INFORMATION additionalStreamInfo = {};
if (pExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ASSERTION_FAILURE && pExceptionInfo->ExceptionRecord->NumberParameters > 0)
{
additionalStream.Type = CommentStreamA;
additionalStream.Buffer = reinterpret_cast<PVOID>(pExceptionInfo->ExceptionRecord->ExceptionInformation[0]);
additionalStream.BufferSize = strlen(reinterpret_cast<char const*>(pExceptionInfo->ExceptionRecord->ExceptionInformation[0])) + 1;
additionalStreamInfo.UserStreamArray = &additionalStream;
additionalStreamInfo.UserStreamCount = 1;
}
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
m_hDumpFile, MiniDumpWithIndirectlyReferencedMemory, &info, nullptr, nullptr);
m_hDumpFile, MiniDumpWithIndirectlyReferencedMemory, &info, &additionalStreamInfo, nullptr);
CloseHandle(m_hDumpFile);
}
@@ -504,6 +518,11 @@ PEXCEPTION_POINTERS pExceptionInfo)
Log(_T("Exception code: %08X %s\r\n"),
pExceptionRecord->ExceptionCode,
GetExceptionString(pExceptionRecord->ExceptionCode));
if (pExceptionRecord->ExceptionCode == EXCEPTION_ASSERTION_FAILURE && pExceptionRecord->NumberParameters >= 2)
{
pExceptionRecord->ExceptionAddress = reinterpret_cast<PVOID>(pExceptionRecord->ExceptionInformation[1]);
Log(_T("Assertion message: %s\r\n"), pExceptionRecord->ExceptionInformation[0]);
}
// Now print information about where the fault occured
TCHAR szFaultingModule[MAX_PATH];