diff --git a/lib/exceptionhandler/dumpinfo.cpp b/lib/exceptionhandler/dumpinfo.cpp index a4c4858d7..559621e92 100644 --- a/lib/exceptionhandler/dumpinfo.cpp +++ b/lib/exceptionhandler/dumpinfo.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include "dumpinfo.h" @@ -40,24 +41,88 @@ extern "C" # define PACKAGE_DISTRIBUTOR "UNKNOWN" #endif -static char* dbgHeader = NULL; +static const std::size_t max_debug_messages = 20; -static void dumpstr(const DumpFileHandle file, const char * const str) +static char* dbgHeader = NULL; +static std::deque > dbgMessages; + +static void dumpstr(const DumpFileHandle file, const char * const str, std::size_t const size) { #if defined(WZ_OS_WIN) DWORD lNumberOfBytesWritten; - WriteFile(file, str, strlen(str), &lNumberOfBytesWritten, NULL); + WriteFile(file, str, size, &lNumberOfBytesWritten, NULL); #else - write(file, str, strlen(str)); + write(file, str, size); #endif } +static void dumpstr(const DumpFileHandle file, const char * const str) +{ + dumpstr(file, str, strlen(str)); +} + +static void dumpEOL(const DumpFileHandle file) +{ +#if defined(WZ_OS_WIN) + dumpstr(file, "\r\n"); +#else + dumpstr(file, "\n"); +#endif +} + +static void debug_exceptionhandler_data(void **, const char * const str) +{ + ASSERT(str != NULL, "Empty string sent to debug callback"); + + // Push this message on the message list + const char * last = &str[strlen(str)]; + + // Strip finishing newlines + while (last != str + && *(last - 1) == '\n') + { + --last; + } + + dbgMessages.push_back(std::vector(str, last)); + + // Ensure the message list's maximum size is maintained + while (dbgMessages.size() > max_debug_messages) + { + dbgMessages.pop_front(); + } +} + void dbgDumpHeader(DumpFileHandle file) { if (dbgHeader) + { dumpstr(file, dbgHeader); + } else - dumpstr(file, "No debug header available (yet)!\n" ); + { + dumpstr(file, "No debug header available (yet)!"); + dumpEOL(file); + } +} + +void dbgDumpLog(DumpFileHandle file) +{ + unsigned int line_num = 1; + + // Write all messages to the given file + for (std::deque >::const_iterator + msg = dbgMessages.begin(); + msg != dbgMessages.end(); + ++msg) + { + dumpstr(file, "Log message: "); + dumpstr(file, &(*msg)[0], msg->size()); + dumpEOL(file); + } + + // Terminate with a separating newline + dumpEOL(file); } static std::string getProgramPath(const char* programCommand) @@ -183,5 +248,6 @@ static void createHeader(int const argc, char* argv[]) void dbgDumpInit(int argc, char* argv[]) { + debug_register_callback(&debug_exceptionhandler_data, NULL, NULL, NULL ); createHeader(argc, argv); } diff --git a/lib/exceptionhandler/dumpinfo.h b/lib/exceptionhandler/dumpinfo.h index aa463efd3..d75e8e726 100644 --- a/lib/exceptionhandler/dumpinfo.h +++ b/lib/exceptionhandler/dumpinfo.h @@ -36,6 +36,13 @@ typedef int DumpFileHandle; extern void dbgDumpHeader(DumpFileHandle file); +/** Dump last several debug log calls into given file descriptor. + * For exception handler. + * + * @param file file descriptor to write to. + */ +extern void dbgDumpLog(DumpFileHandle file); + extern void dbgDumpInit(int argc, char* argv[]); #if defined(__cplusplus) diff --git a/lib/exceptionhandler/exceptionhandler.c b/lib/exceptionhandler/exceptionhandler.c index 6cb94d431..eb1eb552c 100644 --- a/lib/exceptionhandler/exceptionhandler.c +++ b/lib/exceptionhandler/exceptionhandler.c @@ -608,7 +608,7 @@ static void posixExceptionHandler(int signum, siginfo_t * siginfo, WZ_DECL_UNUSE write(dumpFile, signal, strlen(signal)); write(dumpFile, "\n\n", 2); - dumpLog(dumpFile); // dump out the last two log calls + dbgDumpLog(dumpFile); // dump out the last several log calls # if defined(__GLIBC__) // Dump raw backtrace in case GDB is not available or fails diff --git a/lib/exceptionhandler/exchndl.c b/lib/exceptionhandler/exchndl.c index 4ccfba330..8926c9b25 100644 --- a/lib/exceptionhandler/exchndl.c +++ b/lib/exceptionhandler/exchndl.c @@ -1021,7 +1021,7 @@ void GenerateExceptionReport(PEXCEPTION_POINTERS pExceptionInfo) rprintf(".\r\n\r\n"); - dumpLog(hReportFile); + dbgDumpLog(hReportFile); pContext = pExceptionInfo->ContextRecord; diff --git a/lib/framework/debug.c b/lib/framework/debug.c index 9eaf8633f..e3a6f5c01 100644 --- a/lib/framework/debug.c +++ b/lib/framework/debug.c @@ -276,44 +276,6 @@ BOOL debug_enable_switch(const char *str) return (part != LOG_LAST); } -/* Dump last two debug log calls into file descriptor. For exception handler. */ -#if defined(WZ_OS_WIN) -static inline void dumpstr(HANDLE file, const char* str) -{ - DWORD lNumberOfBytesWritten; - WriteFile(file, str, strnlen1(str, MAX_LEN_LOG_LINE) - 1, &lNumberOfBytesWritten, NULL); -} -static inline void dumpEOL(HANDLE file) -{ - DWORD lNumberOfBytesWritten; - WriteFile(file, "\r\n", strlen("\r\n"), &lNumberOfBytesWritten, NULL); -} -#else -static inline void dumpstr(int file, const char* str) -{ - write(file, str, strnlen1(str, MAX_LEN_LOG_LINE) - 1); -} -static inline void dumpEOL(int file) -{ - write(file, "\n", strlen("\n")); -} -#endif - -#if defined(WZ_OS_WIN) -void dumpLog(HANDLE file) -#else -void dumpLog(int file) -#endif -{ - dumpstr(file, "Log message 1: "); - dumpstr(file, inputBuffer[0]); - dumpEOL(file); - dumpstr(file, "Log message 2: "); - dumpstr(file, inputBuffer[1]); - dumpEOL(file); - dumpEOL(file); -} - /** Send the given string to all debug callbacks. * * @param str The string to send to debug callbacks. diff --git a/lib/framework/debug.h b/lib/framework/debug.h index 7e00d4c79..b56997358 100644 --- a/lib/framework/debug.h +++ b/lib/framework/debug.h @@ -190,13 +190,6 @@ static inline void objTraceDisable(void) { traceID = (UDWORD)-1; } } #endif -/** Dump last two debug log calls into given file descriptor. For exception handler. */ -#if defined(WZ_OS_WIN) -extern void dumpLog(HANDLE file); -#else -extern void dumpLog(int file); -#endif - /** Checks if a particular debub flag was enabled */ extern bool debugPartEnabled(code_part codePart);