mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 19:45:23 -04:00
C client: Log much more info for debugging crashes on windows
This commit is contained in:
parent
1aa7c57a62
commit
f265cf8044
@ -342,7 +342,7 @@ ReturnCode Bitmap_DecodePng(Bitmap* bmp, struct Stream* stream) {
|
|||||||
for (i = 0; i < PNG_PALETTE; i++) {
|
for (i = 0; i < PNG_PALETTE; i++) {
|
||||||
palette[i] = PackedCol_ARGB(0, 0, 0, 255);
|
palette[i] = PackedCol_ARGB(0, 0, 0, 255);
|
||||||
}
|
}
|
||||||
bool gotHeader = false, readingChunks = true;
|
bool readingChunks = true;
|
||||||
|
|
||||||
struct InflateState inflate;
|
struct InflateState inflate;
|
||||||
struct Stream compStream;
|
struct Stream compStream;
|
||||||
@ -363,7 +363,6 @@ ReturnCode Bitmap_DecodePng(Bitmap* bmp, struct Stream* stream) {
|
|||||||
switch (fourCC) {
|
switch (fourCC) {
|
||||||
case PNG_FourCC('I','H','D','R'): {
|
case PNG_FourCC('I','H','D','R'): {
|
||||||
if (dataSize != PNG_IHDR_SIZE) return PNG_ERR_INVALID_HEADER_SIZE;
|
if (dataSize != PNG_IHDR_SIZE) return PNG_ERR_INVALID_HEADER_SIZE;
|
||||||
gotHeader = true;
|
|
||||||
res = Stream_Read(stream, buffer, PNG_IHDR_SIZE);
|
res = Stream_Read(stream, buffer, PNG_IHDR_SIZE);
|
||||||
if (res) return res;
|
if (res) return res;
|
||||||
|
|
||||||
@ -442,6 +441,7 @@ ReturnCode Bitmap_DecodePng(Bitmap* bmp, struct Stream* stream) {
|
|||||||
while (!zlibHeader.Done) {
|
while (!zlibHeader.Done) {
|
||||||
if ((res = ZLibHeader_Read(&datStream, &zlibHeader))) return res;
|
if ((res = ZLibHeader_Read(&datStream, &zlibHeader))) return res;
|
||||||
}
|
}
|
||||||
|
if (!bmp->Scan0) return PNG_ERR_NO_DATA;
|
||||||
|
|
||||||
UInt32 bufferLen = bufferRows * scanlineBytes, bufferMax = bufferLen - scanlineBytes;
|
UInt32 bufferLen = bufferRows * scanlineBytes, bufferMax = bufferLen - scanlineBytes;
|
||||||
while (curY < bmp->Height) {
|
while (curY < bmp->Height) {
|
||||||
|
@ -661,8 +661,8 @@ static ReturnCode Inflate_StreamRead(struct Stream* stream, UInt8* data, UInt32
|
|||||||
|
|
||||||
UInt8* cur = state->NextIn;
|
UInt8* cur = state->NextIn;
|
||||||
UInt32 read, remaining = (UInt32)(inputEnd - state->NextIn);
|
UInt32 read, remaining = (UInt32)(inputEnd - state->NextIn);
|
||||||
ReturnCode code = state->Source->Read(state->Source, cur, remaining, &read);
|
ReturnCode res = state->Source->Read(state->Source, cur, remaining, &read);
|
||||||
if (code != 0) return code;
|
if (res) return res;
|
||||||
|
|
||||||
/* Did we fail to read in more input data? Can't immediately return here, */
|
/* Did we fail to read in more input data? Can't immediately return here, */
|
||||||
/* because there might be a few bits of data left in the bit buffer */
|
/* because there might be a few bits of data left in the bit buffer */
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
#include "Chat.h"
|
#include "Chat.h"
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
#include "Funcs.h"
|
#include "Funcs.h"
|
||||||
|
#include "Stream.h"
|
||||||
|
|
||||||
static void ErrorHandler_FailCore(ReturnCode result, const char* raw_msg, void* ctx);
|
static void ErrorHandler_FailCommon(ReturnCode result, const char* raw_msg, void* ctx);
|
||||||
static void ErrorHandler_Backtrace(STRING_TRANSIENT String* str, void* ctx);
|
static void ErrorHandler_DumpCommon(STRING_TRANSIENT String* str, void* ctx);
|
||||||
static void ErrorHandler_Registers(STRING_TRANSIENT String* str, void* ctx);
|
|
||||||
|
|
||||||
#if CC_BUILD_WIN
|
#if CC_BUILD_WIN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
@ -19,6 +19,160 @@ static void ErrorHandler_Registers(STRING_TRANSIENT String* str, void* ctx);
|
|||||||
struct StackPointers { UInt64 Instruction, Frame, Stack; };
|
struct StackPointers { UInt64 Instruction, Frame, Stack; };
|
||||||
struct SymbolAndName { IMAGEHLP_SYMBOL64 Symbol; char Name[256]; };
|
struct SymbolAndName { IMAGEHLP_SYMBOL64 Symbol; char Name[256]; };
|
||||||
|
|
||||||
|
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*-------------------------------------------------------Info dumping------------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
|
static Int32 ErrorHandler_GetFrames(CONTEXT* ctx, struct StackPointers* pointers, Int32 max) {
|
||||||
|
STACKFRAME64 frame = { 0 };
|
||||||
|
frame.AddrPC.Mode = AddrModeFlat;
|
||||||
|
frame.AddrFrame.Mode = AddrModeFlat;
|
||||||
|
frame.AddrStack.Mode = AddrModeFlat;
|
||||||
|
DWORD type;
|
||||||
|
|
||||||
|
#ifdef _M_IX86
|
||||||
|
type = IMAGE_FILE_MACHINE_I386;
|
||||||
|
frame.AddrPC.Offset = ctx->Eip;
|
||||||
|
frame.AddrFrame.Offset = ctx->Ebp;
|
||||||
|
frame.AddrStack.Offset = ctx->Esp;
|
||||||
|
#elif _M_X64
|
||||||
|
type = IMAGE_FILE_MACHINE_AMD64;
|
||||||
|
frame.AddrPC.Offset = ctx->Rip;
|
||||||
|
frame.AddrFrame.Offset = ctx->Rsp;
|
||||||
|
frame.AddrStack.Offset = ctx->Rsp;
|
||||||
|
#elif _M_IA64
|
||||||
|
type = IMAGE_FILE_MACHINE_IA64;
|
||||||
|
frame.AddrPC.Offset = ctx->StIIP;
|
||||||
|
frame.AddrFrame.Offset = ctx->IntSp;
|
||||||
|
frame.AddrBStore.Offset = ctx->RsBSP;
|
||||||
|
frame.AddrStack.Offset = ctx->IntSp;
|
||||||
|
frame.AddrBStore.Mode = AddrModeFlat;
|
||||||
|
#else
|
||||||
|
#error "Unknown machine type"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
HANDLE process = GetCurrentProcess();
|
||||||
|
HANDLE thread = GetCurrentThread();
|
||||||
|
Int32 count;
|
||||||
|
CONTEXT copy = *ctx;
|
||||||
|
|
||||||
|
for (count = 0; count < max; count++) {
|
||||||
|
if (!StackWalk64(type, process, thread, &frame, ©, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) break;
|
||||||
|
if (!frame.AddrFrame.Offset) break;
|
||||||
|
|
||||||
|
pointers[count].Instruction = frame.AddrPC.Offset;
|
||||||
|
pointers[count].Frame = frame.AddrFrame.Offset;
|
||||||
|
pointers[count].Stack = frame.AddrStack.Offset;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL CALLBACK ErrorHandler_DumpModule(const char* name, DWORD64 base, ULONG size, void* ctx) {
|
||||||
|
char buffer[STRING_SIZE * 4];
|
||||||
|
String str = String_FromArray(buffer);
|
||||||
|
DWORD64 end = base + (size - 1);
|
||||||
|
|
||||||
|
String_Format3(&str, "%c = %x-%x\r\n", name, &base, &end);
|
||||||
|
ErrorHandler_Log(&str);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ErrorHandler_Backtrace(STRING_TRANSIENT String* backtrace, void* ctx) {
|
||||||
|
struct SymbolAndName sym = { 0 };
|
||||||
|
sym.Symbol.MaxNameLength = 255;
|
||||||
|
sym.Symbol.SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
||||||
|
|
||||||
|
HANDLE process = GetCurrentProcess();
|
||||||
|
struct StackPointers pointers[40];
|
||||||
|
Int32 i, frames = ErrorHandler_GetFrames((CONTEXT*)ctx, pointers, 40);
|
||||||
|
|
||||||
|
for (i = 0; i < frames; i++) {
|
||||||
|
Int32 number = i + 1;
|
||||||
|
UInt64 addr = (UInt64)pointers[i].Instruction;
|
||||||
|
|
||||||
|
char strBuffer[STRING_SIZE * 10];
|
||||||
|
String str = String_FromArray(strBuffer);
|
||||||
|
|
||||||
|
/* instruction pointer */
|
||||||
|
if (SymGetSymFromAddr64(process, addr, NULL, &sym.Symbol)) {
|
||||||
|
String_Format3(&str, "%i) 0x%x - %c\r\n", &number, &addr, sym.Symbol.Name);
|
||||||
|
} else {
|
||||||
|
String_Format2(&str, "%i) 0x%x\r\n", &number, &addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* frame and stack address */
|
||||||
|
String_AppendString(backtrace, &str);
|
||||||
|
String_Format2(&str, " fp: %x, sp: %x\r\n", &pointers[i].Frame, &pointers[i].Stack);
|
||||||
|
|
||||||
|
/* line number */
|
||||||
|
IMAGEHLP_LINE64 line = { 0 };
|
||||||
|
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||||
|
if (SymGetLineFromAddr64(process, addr, &number, &line)) {
|
||||||
|
String_Format2(&str, " line %i in %c\r\n", &line.LineNumber, line.FileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* module address is in */
|
||||||
|
IMAGEHLP_MODULE64 module = { 0 };
|
||||||
|
module.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
|
||||||
|
if (SymGetModuleInfo64(process, addr, &module)) {
|
||||||
|
String_Format2(&str, " in module %c (%c)\r\n", module.ModuleName, module.ImageName);
|
||||||
|
}
|
||||||
|
ErrorHandler_Log(&str);
|
||||||
|
}
|
||||||
|
String_AppendConst(backtrace, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ErrorHandler_DumpCommon(STRING_TRANSIENT String* str, void* ctx) {
|
||||||
|
HANDLE process = GetCurrentProcess();
|
||||||
|
SymInitialize(process, NULL, TRUE);
|
||||||
|
|
||||||
|
String backtrace = String_FromConst("-- backtrace --\r\n");
|
||||||
|
ErrorHandler_Log(&backtrace);
|
||||||
|
ErrorHandler_Backtrace(str, ctx);
|
||||||
|
|
||||||
|
String modules = String_FromConst("-- modules --\r\n");
|
||||||
|
ErrorHandler_Log(&modules);
|
||||||
|
EnumerateLoadedModules64(process, ErrorHandler_DumpModule, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ErrorHandler_DumpRegisters(CONTEXT* ctx) {
|
||||||
|
char strBuffer[STRING_SIZE * 8];
|
||||||
|
String str = String_FromArray(strBuffer);
|
||||||
|
String_AppendConst(&str, "-- registers --\r\n");
|
||||||
|
|
||||||
|
#ifdef _M_IX86
|
||||||
|
String_Format3(&str, "eax=%y ebx=%y ecx=%y\r\n", &ctx->Eax, &ctx->Ebx, &ctx->Ecx);
|
||||||
|
String_Format3(&str, "edx=%y esi=%y edi=%y\r\n", &ctx->Edx, &ctx->Esi, &ctx->Edi);
|
||||||
|
String_Format3(&str, "eip=%y ebp=%y esp=%y\r\n", &ctx->Eip, &ctx->Ebp, &ctx->Esp);
|
||||||
|
#elif _M_X64
|
||||||
|
String_Format3(&str, "rax=%x rbx=%x rcx=%x\r\n", &ctx->Rax, &ctx->Rbx, &ctx->Rcx);
|
||||||
|
String_Format3(&str, "rdx=%x rsi=%x rdi=%x\r\n", &ctx->Rdx, &ctx->Rsi, &ctx->Rdi);
|
||||||
|
String_Format3(&str, "rip=%x rbp=%x rsp=%x\r\n", &ctx->Rip, &ctx->Rbp, &ctx->Rsp);
|
||||||
|
String_Format3(&str, "r8 =%x r9 =%x r10=%x\r\n", &ctx->R8, &ctx->R9, &ctx->R10);
|
||||||
|
String_Format3(&str, "r11=%x r12=%x r13=%x\r\n", &ctx->R11, &ctx->R12, &ctx->R13);
|
||||||
|
String_Format2(&str, "r14=%x r15=%x\r\n" , &ctx->R14, &ctx->R15);
|
||||||
|
#elif _M_IA64
|
||||||
|
String_Format3(&str, "r1 =%x r2 =%x r3 =%x\r\n", &ctx->IntGp, &ctx->IntT0, &ctx->IntT1);
|
||||||
|
String_Format3(&str, "r4 =%x r5 =%x r6 =%x\r\n", &ctx->IntS0, &ctx->IntS1, &ctx->IntS2);
|
||||||
|
String_Format3(&str, "r7 =%x r8 =%x r9 =%x\r\n", &ctx->IntS3, &ctx->IntV0, &ctx->IntT2);
|
||||||
|
String_Format3(&str, "r10=%x r11=%x r12=%x\r\n", &ctx->IntT3, &ctx->IntT4, &ctx->IntSp);
|
||||||
|
String_Format3(&str, "r13=%x r14=%x r15=%x\r\n", &ctx->IntTeb, &ctx->IntT5, &ctx->IntT6);
|
||||||
|
String_Format3(&str, "r16=%x r17=%x r18=%x\r\n", &ctx->IntT7, &ctx->IntT8, &ctx->IntT9);
|
||||||
|
String_Format3(&str, "r19=%x r20=%x r21=%x\r\n", &ctx->IntT10, &ctx->IntT11, &ctx->IntT12);
|
||||||
|
String_Format3(&str, "r22=%x r23=%x r24=%x\r\n", &ctx->IntT13, &ctx->IntT14, &ctx->IntT15);
|
||||||
|
String_Format3(&str, "r25=%x r26=%x r27=%x\r\n", &ctx->IntT16, &ctx->IntT17, &ctx->IntT18);
|
||||||
|
String_Format3(&str, "r28=%x r29=%x r30=%x\r\n", &ctx->IntT19, &ctx->IntT20, &ctx->IntT21);
|
||||||
|
String_Format3(&str, "r31=%x nat=%x pre=%x\r\n", &ctx->IntT22, &ctx->IntNats,&ctx->Preds);
|
||||||
|
#else
|
||||||
|
#error "Unknown machine type"
|
||||||
|
#endif
|
||||||
|
ErrorHandler_Log(&str);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*------------------------------------------------------Error handling-----------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
static LONG WINAPI ErrorHandler_UnhandledFilter(struct _EXCEPTION_POINTERS* pInfo) {
|
static LONG WINAPI ErrorHandler_UnhandledFilter(struct _EXCEPTION_POINTERS* pInfo) {
|
||||||
/* TODO: Write processor state to file*/
|
/* TODO: Write processor state to file*/
|
||||||
char msgBuffer[128 + 1] = { 0 };
|
char msgBuffer[128 + 1] = { 0 };
|
||||||
@ -28,13 +182,13 @@ static LONG WINAPI ErrorHandler_UnhandledFilter(struct _EXCEPTION_POINTERS* pInf
|
|||||||
UInt64 addr = (UInt64)pInfo->ExceptionRecord->ExceptionAddress;
|
UInt64 addr = (UInt64)pInfo->ExceptionRecord->ExceptionAddress;
|
||||||
String_Format2(&msg, "Unhandled exception 0x%y at 0x%x", &code, &addr);
|
String_Format2(&msg, "Unhandled exception 0x%y at 0x%x", &code, &addr);
|
||||||
|
|
||||||
ErrorHandler_FailCore(0, msg.buffer, pInfo->ContextRecord);
|
ErrorHandler_DumpRegisters(pInfo->ContextRecord);
|
||||||
|
ErrorHandler_FailCommon(0, msg.buffer, pInfo->ContextRecord);
|
||||||
return EXCEPTION_EXECUTE_HANDLER; /* TODO: different flag */
|
return EXCEPTION_EXECUTE_HANDLER; /* TODO: different flag */
|
||||||
}
|
}
|
||||||
|
|
||||||
void ErrorHandler_Init(const char* logFile) {
|
void ErrorHandler_Init(const char* logFile) {
|
||||||
SetUnhandledExceptionFilter(ErrorHandler_UnhandledFilter);
|
SetUnhandledExceptionFilter(ErrorHandler_UnhandledFilter);
|
||||||
/* TODO: Open log file */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ErrorHandler_ShowDialog(const char* title, const char* msg) {
|
void ErrorHandler_ShowDialog(const char* title, const char* msg) {
|
||||||
@ -85,91 +239,21 @@ void ErrorHandler_FailWithCode(ReturnCode result, const char* raw_msg) {
|
|||||||
ctx.ContextFlags = CONTEXT_CONTROL;
|
ctx.ContextFlags = CONTEXT_CONTROL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ErrorHandler_FailCore(result, raw_msg, &ctx);
|
ErrorHandler_FailCommon(result, raw_msg, &ctx);
|
||||||
}
|
}
|
||||||
#if _MSC_VER
|
#if _MSC_VER
|
||||||
#pragma optimize ("", on)
|
#pragma optimize ("", on)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static Int32 ErrorHandler_GetFrames(CONTEXT* ctx, struct StackPointers* pointers, Int32 max) {
|
|
||||||
STACKFRAME64 frame = { 0 };
|
|
||||||
frame.AddrPC.Mode = AddrModeFlat;
|
|
||||||
frame.AddrFrame.Mode = AddrModeFlat;
|
|
||||||
frame.AddrStack.Mode = AddrModeFlat;
|
|
||||||
DWORD type;
|
|
||||||
|
|
||||||
#ifdef _M_IX86
|
|
||||||
type = IMAGE_FILE_MACHINE_I386;
|
|
||||||
frame.AddrPC.Offset = ctx->Eip;
|
|
||||||
frame.AddrFrame.Offset = ctx->Ebp;
|
|
||||||
frame.AddrStack.Offset = ctx->Esp;
|
|
||||||
#elif _M_X64
|
|
||||||
type = IMAGE_FILE_MACHINE_AMD64;
|
|
||||||
frame.AddrPC.Offset = ctx->Rip;
|
|
||||||
frame.AddrFrame.Offset = ctx->Rsp;
|
|
||||||
frame.AddrStack.Offset = ctx->Rsp;
|
|
||||||
#elif _M_IA64
|
|
||||||
type = IMAGE_FILE_MACHINE_IA64;
|
|
||||||
frame.AddrPC.Offset = ctx->StIIP;
|
|
||||||
frame.AddrFrame.Offset = ctx->IntSp;
|
|
||||||
frame.AddrBStore.Offset = ctx->RsBSP;
|
|
||||||
frame.AddrStack.Offset = ctx->IntSp;
|
|
||||||
frame.AddrBStore.Mode = AddrModeFlat;
|
|
||||||
#else
|
|
||||||
#error "Unknown machine type"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
HANDLE process = GetCurrentProcess();
|
|
||||||
HANDLE thread = GetCurrentThread();
|
|
||||||
Int32 count;
|
|
||||||
CONTEXT copy = *ctx;
|
|
||||||
|
|
||||||
for (count = 0; count < max; count++) {
|
|
||||||
if (!StackWalk64(type, process, thread, &frame, ©, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) break;
|
|
||||||
if (!frame.AddrFrame.Offset) break;
|
|
||||||
|
|
||||||
pointers[count].Instruction = frame.AddrPC.Offset;
|
|
||||||
pointers[count].Frame = frame.AddrFrame.Offset;
|
|
||||||
pointers[count].Stack = frame.AddrStack.Offset;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ErrorHandler_Backtrace(STRING_TRANSIENT String* str, void* ctx) {
|
|
||||||
HANDLE process = GetCurrentProcess();
|
|
||||||
SymInitialize(process, NULL, TRUE);
|
|
||||||
|
|
||||||
struct SymbolAndName sym = { 0 };
|
|
||||||
sym.Symbol.MaxNameLength = 255;
|
|
||||||
sym.Symbol.SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
|
||||||
|
|
||||||
struct StackPointers pointers[40];
|
|
||||||
Int32 frames = ErrorHandler_GetFrames((CONTEXT*)ctx, pointers, 40);
|
|
||||||
|
|
||||||
String_AppendConst(str, "\r\nBacktrace: \r\n");
|
|
||||||
Int32 i;
|
|
||||||
|
|
||||||
for (i = 0; i < frames; i++) {
|
|
||||||
Int32 number = i + 1;
|
|
||||||
UInt64 addr = (UInt64)pointers[i].Instruction;
|
|
||||||
|
|
||||||
/* TODO: Log ESP and EBP here too */
|
|
||||||
/* TODO: SymGetLineFromAddr64 as well? */
|
|
||||||
/* TODO: Log module here too */
|
|
||||||
if (SymGetSymFromAddr64(process, addr, NULL, &sym.Symbol)) {
|
|
||||||
String_Format3(str, "%i) 0x%x - %c\r\n", &number, &addr, sym.Symbol.Name);
|
|
||||||
} else {
|
|
||||||
String_Format2(str, "%i) 0x%x\r\n", &number, &addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String_AppendConst(str, "\r\n");
|
|
||||||
}
|
|
||||||
#elif CC_BUILD_NIX
|
#elif CC_BUILD_NIX
|
||||||
#include <X11/X.h>
|
#include <X11/X.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <X11/keysym.h>
|
#include <X11/keysym.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*-----------------------------------------------------X11 message box-----------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
Display* dpy;
|
Display* dpy;
|
||||||
unsigned long X11_Col(UInt8 r, UInt8 g, UInt8 b) {
|
unsigned long X11_Col(UInt8 r, UInt8 g, UInt8 b) {
|
||||||
Colormap cmap = XDefaultColormap(dpy, DefaultScreen(dpy));
|
Colormap cmap = XDefaultColormap(dpy, DefaultScreen(dpy));
|
||||||
@ -389,6 +473,10 @@ static void X11_MessageBox(const char* title, const char* text, X11Window* w) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*------------------------------------------------------Error handling-----------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
void ErrorHandler_Init(const char* logFile) {
|
void ErrorHandler_Init(const char* logFile) {
|
||||||
/* TODO: Implement this */
|
/* TODO: Implement this */
|
||||||
}
|
}
|
||||||
@ -401,35 +489,53 @@ void ErrorHandler_ShowDialog(const char* title, const char* msg) {
|
|||||||
X11Window_Free(&w);
|
X11Window_Free(&w);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ErrorHandler_Backtrace(STRING_TRANSIENT String* str, void* ctx) {
|
void ErrorHandler_DumpCommon(STRING_TRANSIENT String* str, void* ctx) {
|
||||||
/* TODO: Implement this */
|
/* TODO: Implement this */
|
||||||
}
|
}
|
||||||
|
|
||||||
void ErrorHandler_FailWithCode(ReturnCode result, const char* raw_msg) {
|
void ErrorHandler_FailWithCode(ReturnCode result, const char* raw_msg) {
|
||||||
/* TODO: Implement this */
|
/* TODO: Implement this */
|
||||||
ErrorHandler_FailCore(result, raw_msg, NULL);
|
ErrorHandler_FailCommon(result, raw_msg, NULL);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void ErrorHandler_FailCore(ReturnCode result, const char* raw_msg, void* ctx) {
|
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*----------------------------------------------------------Common---------------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
|
void* logFile;
|
||||||
|
struct Stream logStream;
|
||||||
|
bool logOpen;
|
||||||
|
|
||||||
|
void ErrorHandler_Log(STRING_PURE String* msg) {
|
||||||
|
if (!logOpen) {
|
||||||
|
logOpen = true;
|
||||||
|
String path = String_FromConst("client.log");
|
||||||
|
|
||||||
|
ReturnCode res = File_Append(&logFile, &path);
|
||||||
|
if (!res) Stream_FromFile(&logStream, logFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!logStream.Meta.File) return;
|
||||||
|
Stream_Write(&logStream, msg->buffer, msg->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ErrorHandler_FailCommon(ReturnCode result, const char* raw_msg, void* ctx) {
|
||||||
char logMsgBuffer[3070 + 1] = { 0 };
|
char logMsgBuffer[3070 + 1] = { 0 };
|
||||||
String logMsg = { logMsgBuffer, 0, 3070 };
|
String logMsg = { logMsgBuffer, 0, 3070 };
|
||||||
|
|
||||||
String_Format1(&logMsg, "ClassiCube crashed.\nMessge: %c\n", raw_msg);
|
String_Format1(&logMsg, "ClassiCube crashed.\nMessge: %c\n", raw_msg);
|
||||||
if (result) { String_Format1(&logMsg, "%y\n", &result); } else { result = 1; }
|
if (result) { String_Format1(&logMsg, "%y\n", &result); } else { result = 1; }
|
||||||
|
ErrorHandler_Log(&logMsg);
|
||||||
|
|
||||||
//ErrorHandler_Registers(ctx, &logMsg);
|
ErrorHandler_DumpCommon(&logMsg, ctx);
|
||||||
ErrorHandler_Backtrace(&logMsg, ctx);
|
if (logStream.Meta.File) File_Close(logFile);
|
||||||
/* TODO: write to log file */
|
|
||||||
|
|
||||||
|
String_AppendConst(&logMsg, "Full details of the crash have been logged to 'client.log'.\n");
|
||||||
String_AppendConst(&logMsg,
|
String_AppendConst(&logMsg,
|
||||||
"Please report the crash to github.com/UnknownShadow200/ClassicalSharp/issues so we can fix it.");
|
"Please report the crash to github.com/UnknownShadow200/ClassicalSharp/issues so we can fix it.");
|
||||||
ErrorHandler_ShowDialog("We're sorry", logMsg.buffer);
|
ErrorHandler_ShowDialog("We're sorry", logMsg.buffer);
|
||||||
Platform_Exit(result);
|
Platform_Exit(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ErrorHandler_Log(STRING_PURE String* msg) {
|
|
||||||
/* TODO: write to log file */
|
|
||||||
}
|
|
||||||
|
|
||||||
void ErrorHandler_Fail(const char* raw_msg) { ErrorHandler_FailWithCode(0, raw_msg); }
|
void ErrorHandler_Fail(const char* raw_msg) { ErrorHandler_FailWithCode(0, raw_msg); }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user