mirror of
				https://github.com/AxioDL/logvisor.git
				synced 2025-10-25 19:30:27 +00:00 
			
		
		
		
	Add backtrace print to fatal logvisor errors
This commit is contained in:
		
							parent
							
								
									48dc4c40c7
								
							
						
					
					
						commit
						ac88aa934d
					
				| @ -15,6 +15,8 @@ extern "C" void logvisorBp(); | |||||||
| namespace logvisor | namespace logvisor | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
|  | void logvisorAbort(); | ||||||
|  | 
 | ||||||
| #if _WIN32 && UNICODE | #if _WIN32 && UNICODE | ||||||
| #define LOG_UCS2 1 | #define LOG_UCS2 1 | ||||||
| #endif | #endif | ||||||
| @ -114,6 +116,11 @@ void RegisterConsoleLogger(); | |||||||
|  */ |  */ | ||||||
| void RegisterFileLogger(const char* filepath); | void RegisterFileLogger(const char* filepath); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief Register signal handlers with system for common client exceptions | ||||||
|  |  */ | ||||||
|  | void RegisterStandardExceptions(); | ||||||
|  | 
 | ||||||
| #if _WIN32 | #if _WIN32 | ||||||
| /**
 | /**
 | ||||||
|  * @brief Spawn an application-owned cmd.exe window for displaying console output |  * @brief Spawn an application-owned cmd.exe window for displaying console output | ||||||
| @ -170,7 +177,7 @@ public: | |||||||
|         if (severity == Error || severity == Fatal) |         if (severity == Error || severity == Fatal) | ||||||
|             logvisorBp(); |             logvisorBp(); | ||||||
|         if (severity == Fatal) |         if (severity == Fatal) | ||||||
|             abort(); |             logvisorAbort(); | ||||||
|         else if (severity == Error) |         else if (severity == Error) | ||||||
|             ++ErrorCount; |             ++ErrorCount; | ||||||
|     } |     } | ||||||
| @ -204,7 +211,7 @@ public: | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (severity == Fatal) |         if (severity == Fatal) | ||||||
|             abort(); |             logvisorAbort(); | ||||||
|         else if (severity == Error) |         else if (severity == Error) | ||||||
|             ++ErrorCount; |             ++ErrorCount; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -7,19 +7,19 @@ | |||||||
| #endif | #endif | ||||||
| #include <windows.h> | #include <windows.h> | ||||||
| #include <io.h> | #include <io.h> | ||||||
| #include <fcntl.h> |  | ||||||
| #else | #else | ||||||
| #include <sys/ioctl.h> | #include <sys/ioctl.h> | ||||||
| #include <fcntl.h> |  | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #include <fcntl.h> | ||||||
| #include <chrono> | #include <chrono> | ||||||
| #include <mutex> | #include <mutex> | ||||||
| #include <thread> | #include <thread> | ||||||
| #include <unordered_map> | #include <unordered_map> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <inttypes.h> | #include <inttypes.h> | ||||||
|  | #include <signal.h> | ||||||
| #include "logvisor/logvisor.hpp" | #include "logvisor/logvisor.hpp" | ||||||
| 
 | 
 | ||||||
| /* ANSI sequences */ | /* ANSI sequences */ | ||||||
| @ -39,6 +39,7 @@ void logvisorBp() {} | |||||||
| 
 | 
 | ||||||
| namespace logvisor | namespace logvisor | ||||||
| { | { | ||||||
|  | static Module Log("logvisor"); | ||||||
| 
 | 
 | ||||||
| static std::unordered_map<std::thread::id, const char*> ThreadMap; | static std::unordered_map<std::thread::id, const char*> ThreadMap; | ||||||
| void RegisterThreadName(const char* name) | void RegisterThreadName(const char* name) | ||||||
| @ -66,6 +67,86 @@ void RegisterThreadName(const char* name) | |||||||
| #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #if _WIN32 | ||||||
|  | #include <DbgHelp.h> | ||||||
|  | #pragma comment(lib, "Dbghelp.lib") | ||||||
|  | 
 | ||||||
|  | static void logvisorAbort() | ||||||
|  | { | ||||||
|  |     unsigned int i; | ||||||
|  |     void* stack[100]; | ||||||
|  |     unsigned short frames; | ||||||
|  |     SYMBOL_INFO* symbol; | ||||||
|  |     HANDLE process; | ||||||
|  | 
 | ||||||
|  |     process = GetCurrentProcess(); | ||||||
|  |     SymInitialize(process, NULL, TRUE); | ||||||
|  |     frames = CaptureStackBackTrace(0, 100, stack, NULL); | ||||||
|  |     symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); | ||||||
|  |     symbol->MaxNameLen = 255; | ||||||
|  |     symbol->SizeOfStruct = sizeof(SYMBOL_INFO); | ||||||
|  | 
 | ||||||
|  |     for (i = 0; i < frames; i++) | ||||||
|  |     { | ||||||
|  |         SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); | ||||||
|  | 
 | ||||||
|  |         printf("%i: %s - 0x%0llX", frames - i - 1, symbol->Name, symbol->Address); | ||||||
|  | 
 | ||||||
|  |         DWORD dwDisplacement; | ||||||
|  |         IMAGEHLP_LINE64 line; | ||||||
|  |         SymSetOptions(SYMOPT_LOAD_LINES); | ||||||
|  | 
 | ||||||
|  |         line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); | ||||||
|  |         if (SymGetLineFromAddr64(process, (DWORD64)(stack[i]), &dwDisplacement, &line)) | ||||||
|  |         { | ||||||
|  |             // SymGetLineFromAddr64 returned success
 | ||||||
|  |             printf(" LINE %d\n", line.LineNumber); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             printf("\n"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     free(symbol); | ||||||
|  | 
 | ||||||
|  |     // If you caught one of the above signals, it is likely you just
 | ||||||
|  |     // want to quit your program right now.
 | ||||||
|  |     abort(); | ||||||
|  | } | ||||||
|  | #else | ||||||
|  | 
 | ||||||
|  | #include <execinfo.h> | ||||||
|  | void logvisorAbort() | ||||||
|  | { | ||||||
|  |     void* array[128]; | ||||||
|  |     size_t size = backtrace(array, 128); | ||||||
|  |     char** strings = backtrace_symbols(array, size); | ||||||
|  | 
 | ||||||
|  |     for (size_t i = 0; i < size; i++) | ||||||
|  |        printf("%s\n", strings[i]); | ||||||
|  | 
 | ||||||
|  |     free(strings); | ||||||
|  |     abort(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | static void AbortHandler(int signum) | ||||||
|  | { | ||||||
|  |     switch (signum) | ||||||
|  |     { | ||||||
|  |     case SIGSEGV: | ||||||
|  |         Log.report(logvisor::Fatal, "Segmentation Fault"); | ||||||
|  |     case SIGILL: | ||||||
|  |         Log.report(logvisor::Fatal, "Bad Execution"); | ||||||
|  |     case SIGFPE: | ||||||
|  |         Log.report(logvisor::Fatal, "Floating Point Exception"); | ||||||
|  |     default: | ||||||
|  |         Log.report(logvisor::Fatal, "unknown signal %d", signum); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| std::vector<std::unique_ptr<ILogger>> MainLoggers; | std::vector<std::unique_ptr<ILogger>> MainLoggers; | ||||||
| std::atomic_size_t ErrorCount(0); | std::atomic_size_t ErrorCount(0); | ||||||
| static std::chrono::steady_clock MonoClock; | static std::chrono::steady_clock MonoClock; | ||||||
| @ -314,6 +395,13 @@ void CreateWin32Console() | |||||||
| } | } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | void RegisterStandardExceptions() | ||||||
|  | { | ||||||
|  |     signal(SIGSEGV, AbortHandler); | ||||||
|  |     signal(SIGILL, AbortHandler); | ||||||
|  |     signal(SIGFPE, AbortHandler); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| struct FileLogger : public ILogger | struct FileLogger : public ILogger | ||||||
| { | { | ||||||
|     FILE* fp; |     FILE* fp; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user