diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-03-31 23:58:37 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-03-31 23:58:37 (GMT) |
commit | c912952fb5e8072770262c64932c1d8cf2027cf0 (patch) | |
tree | d21ae1340c96f9fe1105f9cdaa62d84342f58cd9 /apps | |
parent | f64620e28a55dbddaeeefef2e7b8a6a433f21c82 (diff) | |
download | uscxml-c912952fb5e8072770262c64932c1d8cf2027cf0.zip uscxml-c912952fb5e8072770262c64932c1d8cf2027cf0.tar.gz uscxml-c912952fb5e8072770262c64932c1d8cf2027cf0.tar.bz2 |
Various bug-fixes for W3C test conformance and stack traces with exceptions and segfaults
Diffstat (limited to 'apps')
-rw-r--r-- | apps/mmi-browser.cpp | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/apps/mmi-browser.cpp b/apps/mmi-browser.cpp index 56d7f02..6f997e7 100644 --- a/apps/mmi-browser.cpp +++ b/apps/mmi-browser.cpp @@ -6,6 +6,14 @@ #include <signal.h> #endif +#ifdef HAS_EXECINFO_H +#include <execinfo.h> +#endif + +#ifdef HAS_DLFCN_H +#include <dlfcn.h> +#endif + #ifdef _WIN32 #include "XGetopt.h" #endif @@ -30,6 +38,71 @@ class VerboseMonitor : public uscxml::InterpreterMonitor { } }; + +#ifdef HAS_EXECINFO_H +void printBacktrace(void** array, int size) { + char** messages = backtrace_symbols(array, size); + for (int i = 0; i < size && messages != NULL; ++i) { + std::cerr << "\t" << messages[i] << std::endl; + } + std::cerr << std::endl; + free(messages); +} + +#ifdef HAS_DLFCN_H +// see https://gist.github.com/nkuln/2020860 +typedef void (*cxa_throw_type)(void *, void *, void (*) (void *)); +cxa_throw_type orig_cxa_throw = 0; + +void load_orig_throw_code() { + orig_cxa_throw = (cxa_throw_type) dlsym(RTLD_NEXT, "__cxa_throw"); +} + +extern "C" +void __cxa_throw (void *thrown_exception, void *pvtinfo, void (*dest)(void *)) { + std::cerr << __FUNCTION__ << " will throw exception from " << std::endl; + if (orig_cxa_throw == 0) + load_orig_throw_code(); + + void *array[50]; + size_t size = backtrace(array, 50); + printBacktrace(array, size); + orig_cxa_throw(thrown_exception, pvtinfo, dest); +} +#endif +#endif + + +// see http://stackoverflow.com/questions/2443135/how-do-i-find-where-an-exception-was-thrown-in-c +void customTerminate() { + static bool tried_throw = false; + try { + // try once to re-throw currently active exception + if (!tried_throw) { + throw; + tried_throw = true; + } else { + tried_throw = false; + }; + } + catch (const std::exception &e) { + std::cerr << __FUNCTION__ << " caught unhandled exception. what(): " + << e.what() << std::endl; + } + catch (...) { + std::cerr << __FUNCTION__ << " caught unknown/unhandled exception." + << std::endl; + } + +#ifdef HAS_EXECINFO_H + void * array[50]; + int size = backtrace(array, 50); + + printBacktrace(array, size); +#endif + abort(); +} + void printUsageAndExit() { printf("mmi-browser version " USCXML_VERSION " (" CMAKE_BUILD_TYPE " build - " CMAKE_COMPILER_STRING ")\n"); printf("Usage\n"); @@ -48,6 +121,8 @@ void printUsageAndExit() { int main(int argc, char** argv) { using namespace uscxml; + std::set_terminate(customTerminate); + #ifdef HAS_SIGNAL_H signal(SIGPIPE, SIG_IGN); #endif |