always print stack information on errors

This commit is contained in:
Tim Felgentreff 2019-04-06 11:08:00 +02:00
parent 9567787af2
commit 2d98fbb90c
3 changed files with 122 additions and 51 deletions

View file

@ -0,0 +1,68 @@
#ifndef ST_BACKTRACE_H
#define ST_BACKTRACE_H 1
#include "stdio.h"
#ifdef __GLIBC__
#include "execinfo.h"
inline void print_backtrace(void) {
int j, nptrs;
void *buffer[100];
nptrs = backtrace(buffer, 100);
fprintf(stderr, "backtrace() returned %d addresses\n", nptrs);
backtrace_symbols_fd(buffer, 100, 2);
}
#elif defined(USE_WIN32)
#include "windows.h"
#include "dbghelp.h"
#include "process.h"
inline void print_backtrace(void) {
unsigned int i;
void *stack[100];
unsigned short frames;
SYMBOL_INFO *symbol;
HANDLE process;
DWORD displacement;
IMAGEHLP_LINE64 *line;
char* name;
process = GetCurrentProcess();
SymInitialize(process, NULL, TRUE);
frames = CaptureStackBackTrace(0, 100, stack, NULL);
fprintf(stderr, "backtrace returned %d addresses\n", frames);
symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
symbol->MaxNameLen = 1024;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
line = (IMAGEHLP_LINE64 *)malloc(sizeof(IMAGEHLP_LINE64));
line->SizeOfStruct = sizeof(IMAGEHLP_LINE64);
for(i = 0; i < frames; i++) {
SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
if (symbol->Name) {
name = symbol->Name;
} else {
name = "<unknown frame>";
}
if (SymGetLineFromAddr64(process, (DWORD64)(stack[i]), &displacement, line)) {
fprintf("%d: %s in %s:%d 0x%x\n", frames - i - 1, name, line->FileName, line->LineNumber, symbol->Address);
} else {
fprintf("%d: %s 0x%x\n", frames - i - 1, name, symbol->Address);
}
}
free(symbol);
}
#else
inline void print_backtrace(void) {
}
#endif
#endif

View file

@ -210,6 +210,8 @@ extern void beos_init(int argc, char **argv);
#include <stdexcept>
#include <stacktrace/call_stack.hpp>
#include <stacktrace/stack_exception.hpp>
#else
#include "st_backtrace.h"
#endif
#include <stdlib.h>
@ -434,6 +436,8 @@ void ExitFatal(int err)
{
#ifdef USE_STACKTRACE
throw stacktrace::stack_runtime_error((const char*)err);
#else
print_backtrace();
#endif
exit(err);
}
@ -577,7 +581,7 @@ void ParseCommandLine(int argc, char **argv, Parameters &parameters)
if (ZoomNoResize) {
fprintf(stderr, "Error: -Z only works with OpenGL enabled\n");
Usage();
ExitFatal(-1);
exit(-1);
}
continue;
case 'O':
@ -605,7 +609,7 @@ void ParseCommandLine(int argc, char **argv, Parameters &parameters)
if (!sep || !*(sep + 1)) {
fprintf(stderr, "%s: incorrect format of video mode resolution -- '%s'\n", argv[0], optarg);
Usage();
ExitFatal(-1);
exit(-1);
}
Video.ViewportHeight = atoi(sep + 1);
*sep = 0;
@ -613,7 +617,7 @@ void ParseCommandLine(int argc, char **argv, Parameters &parameters)
if (!Video.ViewportHeight || !Video.ViewportWidth) {
fprintf(stderr, "%s: incorrect format of video mode resolution -- '%sx%s'\n", argv[0], optarg, sep + 1);
Usage();
ExitFatal(-1);
exit(-1);
}
#if defined(USE_OPENGL) || defined(USE_GLES)
if (!ZoomNoResize) {
@ -647,7 +651,7 @@ void ParseCommandLine(int argc, char **argv, Parameters &parameters)
if (!sep || !*(sep + 1)) {
fprintf(stderr, "%s: incorrect format of video mode resolution -- '%s'\n", argv[0], optarg);
Usage();
ExitFatal(-1);
exit(-1);
}
Video.Height = atoi(sep + 1);
*sep = 0;
@ -660,7 +664,7 @@ void ParseCommandLine(int argc, char **argv, Parameters &parameters)
case 'h':
default:
Usage();
ExitFatal(-1);
exit(-1);
}
break;
}
@ -731,72 +735,69 @@ int stratagusMain(int argc, char **argv)
Assert(pathPtr);
StratagusLibPath = pathPtr;
#endif
#ifdef USE_STACKTRACE
try {
#endif
Parameters &parameters = Parameters::Instance;
parameters.SetDefaultValues();
parameters.SetLocalPlayerNameFromEnv();
Parameters &parameters = Parameters::Instance;
parameters.SetDefaultValues();
parameters.SetLocalPlayerNameFromEnv();
#ifdef REDIRECT_OUTPUT
RedirectOutput();
RedirectOutput();
#endif
if (argc > 0) {
parameters.applicationName = argv[0];
}
if (argc > 0) {
parameters.applicationName = argv[0];
}
// FIXME: Parse options before or after scripts?
ParseCommandLine(argc, argv, parameters);
// Init the random number generator.
InitSyncRand();
// FIXME: Parse options before or after scripts?
ParseCommandLine(argc, argv, parameters);
// Init the random number generator.
InitSyncRand();
makedir(parameters.GetUserDirectory().c_str(), 0777);
makedir(parameters.GetUserDirectory().c_str(), 0777);
// Init Lua and register lua functions!
InitLua();
LuaRegisterModules();
// Init Lua and register lua functions!
InitLua();
LuaRegisterModules();
// Initialise AI module
InitAiModule();
// Initialise AI module
InitAiModule();
LoadCcl(parameters.luaStartFilename, parameters.luaScriptArguments);
LoadCcl(parameters.luaStartFilename, parameters.luaScriptArguments);
PrintHeader();
PrintLicense();
PrintHeader();
PrintLicense();
// Setup video display
InitVideo();
// Setup video display
InitVideo();
// Setup sound card
if (!InitSound()) {
InitMusic();
}
// Setup sound card
if (!InitSound()) {
InitMusic();
}
#ifndef DEBUG // For debug it's better not to have:
srand(time(NULL)); // Random counter = random each start
srand(time(NULL)); // Random counter = random each start
#endif
// Show title screens.
SetDefaultTextColors(FontYellow, FontWhite);
LoadFonts();
SetClipping(0, 0, Video.Width - 1, Video.Height - 1);
Video.ClearScreen();
ShowTitleScreens();
// Show title screens.
SetDefaultTextColors(FontYellow, FontWhite);
LoadFonts();
SetClipping(0, 0, Video.Width - 1, Video.Height - 1);
Video.ClearScreen();
ShowTitleScreens();
// Init player data
ThisPlayer = NULL;
//Don't clear the Players structure as it would erase the allowed units.
// memset(Players, 0, sizeof(Players));
NumPlayers = 0;
// Init player data
ThisPlayer = NULL;
//Don't clear the Players structure as it would erase the allowed units.
// memset(Players, 0, sizeof(Players));
NumPlayers = 0;
UnitManager.Init(); // Units memory management
PreMenuSetup(); // Load everything needed for menus
UnitManager.Init(); // Units memory management
PreMenuSetup(); // Load everything needed for menus
MenuLoop();
MenuLoop();
Exit(0);
#ifdef USE_STACKTRACE
Exit(0);
} catch (const std::exception &e) {
fprintf(stderr, "Stratagus crashed!\n");
fprintf(stderr, "Please send this call stack to our bug tracker: https://github.com/Wargus/stratagus/issues\n");
@ -805,7 +806,6 @@ int stratagusMain(int argc, char **argv)
fprintf(stderr, "%s", e.what());
exit(1);
}
#endif
return 0;
}

View file

@ -45,6 +45,8 @@
#include <stdexcept>
#include <stacktrace/call_stack.hpp>
#include <stacktrace/stack_exception.hpp>
#else
#include "st_backtrace.h"
#endif
#ifdef USE_X11
@ -530,6 +532,7 @@ void AbortAt(const char *file, int line, const char *funcName, const char *condi
throw stacktrace::stack_runtime_error((const char*)buf);
#else
fprintf(stderr, "%s\n", buf);
print_backtrace();
#endif
fflush(stdout);
fflush(stderr);