diff --git a/CMakeLists.txt b/CMakeLists.txt index ecb8f448d..67e098757 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -652,6 +652,7 @@ endif() find_package(BZip2) find_package(FluidSynth) +find_package(StackTrace) find_package(Mikmod) find_package(MNG) find_package(OggVorbis) @@ -697,6 +698,7 @@ option(WITH_MIKMOD "Compile Stratagus with Mikmod sound library" ON) option(WITH_MNG "Compile Stratagus with MNG image library" ON) option(WITH_OGGVORBIS "Compile Stratagus with OGG/Vorbis sound library" ON) option(WITH_THEORA "Compile Stratagus with Theroa video library" ON) +option(WITH_STACKTRACE "Compile Stratagus with StackTrace library" ON) option(WITH_X11 "Compile Stratagus with X11 clipboard pasting support" ON) @@ -778,6 +780,12 @@ if(WITH_THEORA AND THEORA_FOUND) set(stratagus_LIBS ${stratagus_LIBS} ${THEORA_LIBRARY}) endif() +if(WITH_STACKTRACE AND STACKTRACE_FOUND) + add_definitions(-DUSE_STACKTRACE ${STACKTRACE_DEFINITIONS}) + include_directories(${STACKTRACE_PROJECT_DIR}) + set(stratagus_LIBS ${stratagus_LIBS} ${STACKTRACE_LIBRARY}) +endif() + if(WITH_X11 AND X11_FOUND) add_definitions(-DUSE_X11) include_directories(${X11_INCLUDE_DIR}) @@ -1036,6 +1044,7 @@ log_package("FluidSynth" "FLUIDSYNTH") log_package("MikMod" "MIKMOD") log_package("Mng" "MNG") log_package("Ogg/Vorbis" "OGGVORBIS") +log_package("StackTrace" "STACKTRACE") log_package("Theora" "THEORA") log_package("X11" "X11") diff --git a/cmake/modules/FindStackTrace.cmake b/cmake/modules/FindStackTrace.cmake new file mode 100644 index 000000000..55b822e8e --- /dev/null +++ b/cmake/modules/FindStackTrace.cmake @@ -0,0 +1,28 @@ +# - Try to find the StackTrace library +# Once done this will define +# +# STACKTRACE_FOUND - system has StackTrace +# STACKTRACE_PROJECT_DIR - the StackTrace project directory +# STACKTRACE_LIBRARY - The StackTrace library + +# Copyright (c) 2015, cybermind +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if(STACKTRACE_PROJECT_DIR AND STACKTRACE_LIBRARY) + set(STACKTRACE_FOUND true) +else() + find_path(STACKTRACE_PROJECT_DIR stacktrace/call_stack.hpp stacktrace/stack_exception.hpp) + find_library(STACKTRACE_LIBRARY NAMES StackTrace) + + if(STACKTRACE_PROJECT_DIR AND STACKTRACE_LIBRARY) + set(STACKTRACE_FOUND true) + message(STATUS "Found StackTrace: ${STACKTRACE_LIBRARY}") + else() + set(STACKTRACE_FOUND false) + message(STATUS "Could not find StackTrace") + endif() + + mark_as_advanced(STACKTRACE_PROJECT_DIR STACKTRACE_LIBRARY) +endif() diff --git a/src/stratagus/stratagus.cpp b/src/stratagus/stratagus.cpp index eb0ac368c..47deac325 100644 --- a/src/stratagus/stratagus.cpp +++ b/src/stratagus/stratagus.cpp @@ -208,6 +208,12 @@ extern void beos_init(int argc, char **argv); #include "missile.h" //for FreeBurningBuildingFrames #endif +#ifdef USE_STACKTRACE +#include +#include +#include +#endif + #include #include @@ -679,7 +685,9 @@ int stratagusMain(int argc, char **argv) Assert(pathPtr); StratagusLibPath = pathPtr; #endif - +#ifdef USE_STACKTRACE + try { +#endif Parameters ¶meters = Parameters::Instance; parameters.SetDefaultValues(); parameters.SetLocalPlayerNameFromEnv(); @@ -738,6 +746,16 @@ int stratagusMain(int argc, char **argv) MenuLoop(); Exit(0); +#ifdef USE_STACKTRACE + } catch (const std::exception &e) { + fprintf(stderr, "Stratagus crashed!\n"); + fprintf(stderr, "Please send this call stack to our bug tracker: https://bugs.launchpad.net/stratagus\n"); + fprintf(stderr, "and what have you done to cause this bug.\n"); + fprintf(stderr, " === exception state traceback === \n"); + fprintf(stderr, "%s", e.what()); + ExitFatal(1); + } +#endif return 0; } diff --git a/src/stratagus/util.cpp b/src/stratagus/util.cpp index 6b9ca88f3..fbda304a6 100644 --- a/src/stratagus/util.cpp +++ b/src/stratagus/util.cpp @@ -41,6 +41,12 @@ #include #endif +#ifdef USE_STACKTRACE +#include +#include +#include +#endif + #ifdef USE_X11 #include #include @@ -494,7 +500,13 @@ void PrintLocation(const char *file, int line, const char *funcName) void AbortAt(const char *file, int line, const char *funcName, const char *conditionStr) { - fprintf(stderr, "Assertion failed at %s:%d: %s: %s\n", file, line, funcName, conditionStr); + char buf[1024]; + snprintf(buf, 1024, "Assertion failed at %s:%d: %s: %s\n", file, line, funcName, conditionStr); +#ifdef USE_STACKTRACE + throw stacktrace::stack_runtime_error((const char*)buf); +#else + fprintf(stderr, "%s\n", buf); +#endif fflush(stdout); fflush(stderr); abort();