From 7dc4bc9ca50a60dbd1f30cee6c5cf2e70b13bb89 Mon Sep 17 00:00:00 2001 From: twanvl Date: Sun, 28 Dec 2008 19:18:35 +0000 Subject: [PATCH] try to get stack traces for InternalErrors, it doesn't work yet for errors caught with OnExceptionInMainLoop, because they are rethrown. git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@1260 0fc631ac-6414-0410-93d0-97cfa31319b6 --- src/util/error.cpp | 83 ++++++++++++++++++++++++++++++++++++++++++++++ src/util/error.hpp | 9 ++--- 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/src/util/error.cpp b/src/util/error.cpp index e861b50a..d2a6b5c7 100644 --- a/src/util/error.cpp +++ b/src/util/error.cpp @@ -9,6 +9,10 @@ #include #include #include +#include +#if wxUSE_STACKWALKER + #include +#endif DECLARE_TYPEOF_COLLECTION(ScriptParseError); @@ -43,6 +47,85 @@ String Error::what() const { return message; } + + +// Stolen from wx/appbase.cpp +// we can't just call it, because of static linkage +#if wxUSE_STACKWALKER +String get_stack_trace() { + wxString stackTrace; + + class StackDumper : public wxStackWalker { + public: + StackDumper() {} + + const wxString& GetStackTrace() const { return m_stackTrace; } + + protected: + virtual void OnStackFrame(const wxStackFrame& frame) { + m_stackTrace << wxString::Format(_("[%02d] "), frame.GetLevel()); + + wxString name = frame.GetName(); + if ( !name.empty() ) { + m_stackTrace << wxString::Format(_("%-40s"), name.c_str()); + } else { + m_stackTrace << wxString::Format( + _("%p"), + (void*)frame.GetAddress() + ); + } + + if ( frame.HasSourceLocation() ) { + m_stackTrace << _('\t') + << frame.GetFileName() + << _(':') + << (unsigned int)frame.GetLine(); + } + + m_stackTrace << _('\n'); + } + + private: + wxString m_stackTrace; + }; + + StackDumper dump; + dump.Walk(2); // don't show InternalError() call itself + stackTrace = dump.GetStackTrace(); + + // don't show more than maxLines or we could get a dialog too tall to be + // shown on screen: 20 should be ok everywhere as even with 15 pixel high + // characters it is still only 300 pixels... + static const int maxLines = 20; + const int count = stackTrace.Freq(wxT('\n')); + for ( int i = 0; i < count - maxLines; i++ ) + stackTrace = stackTrace.BeforeLast(wxT('\n')); + + return stackTrace; +} +#else +String get_stack_trace() { + return _(""); // not supported +} +#endif // wxUSE_STACKWALKER + +InternalError::InternalError(const String& str) + : Error( + _("An internal error occured:\n\n") + + str + _("\n") + _("Please save your work (use 'save as' to so you don't overwrite things)\n") + _("and restart Magic Set Editor.\n\n") + _("You should leave a bug report on http://magicseteditor.sourceforge.net/\n") + _("Press Ctrl+C to copy this message to the clipboard.") + ) +{ + // add a stacktrace + const String stack_trace = get_stack_trace(); + if (!stack_trace.empty()) { + message << _("\n\nCall stack:\n") << stack_trace; + } +} + // ----------------------------------------------------------------------------- : Parse errors ScriptParseError::ScriptParseError(size_t pos, int line, const String& filename, const String& error) diff --git a/src/util/error.hpp b/src/util/error.hpp index 9c9e93ab..03ebf084 100644 --- a/src/util/error.hpp +++ b/src/util/error.hpp @@ -27,7 +27,7 @@ class Error { /// Return the error message virtual String what() const; - private: + protected: String message; ///< The error message }; @@ -35,9 +35,7 @@ class Error { /// Internal errors class InternalError : public Error { public: - inline InternalError(const String& str) - : Error(_ERROR_1_("internal error", str.c_str())) - {} + InternalError(const String& str); }; // ----------------------------------------------------------------------------- : File errors @@ -148,6 +146,9 @@ void handle_warning(const String& w, bool now = true); /** Should be called repeatedly (e.g. in an onIdle event handler) */ void handle_pending_errors(); +/// Make a stack trace for use in InternalErrors +String get_stack_trace(); + /// Catch all types of errors, and pass then to handle_error #define CATCH_ALL_ERRORS(handle_now) \ catch (const Error& e) { \