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
This commit is contained in:
twanvl
2008-12-28 19:18:35 +00:00
parent a8b32d145b
commit 7dc4bc9ca5
2 changed files with 88 additions and 4 deletions
+83
View File
@@ -9,6 +9,10 @@
#include <util/prec.hpp>
#include <util/error.hpp>
#include <cli/text_io_handler.hpp>
#include <cli/text_io_handler.hpp>
#if wxUSE_STACKWALKER
#include <wx/stackwalk.h>
#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)
+5 -4
View File
@@ -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) { \