//#include "Exception.ih"
// Custom includes
+#include <execinfo.h>
+#include <sstream>
+#include "../config.hh"
+#include "impl/demangle.h"
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
return message_.c_str();
}
+#ifdef SENF_DEBUG
+prefix_ void senf::Exception::addBacktrace()
+{
+ void * entries[SENF_DEBUG_BACKTRACE_NUMCALLERS];
+ unsigned nEntries( ::backtrace(entries, SENF_DEBUG_BACKTRACE_NUMCALLERS) );
+ char ** symbols = ::backtrace_symbols(entries, nEntries);
+
+ std::stringstream ss;
+ ss << "\nException at\n";
+ for (unsigned i=0; i<nEntries; ++i) {
+ std::string sym (symbols[i]);
+ std::string::size_type fnStart (sym.find("("));
+ if (fnStart != std::string::npos) {
+ std::string::size_type fnEnd (sym.find(")",fnStart+1));
+ if (fnEnd != std::string::npos) {
+ std::string fn (sym,fnStart+1, fnEnd-fnStart-1);
+ char * demangled ( ::cplus_demangle(fn.c_str(),
+ DMGL_TYPES|DMGL_AUTO) );
+ if (demangled) {
+ ss << " " << demangled << "( ... )" << std::string(sym,fnEnd+1) << "\n";
+ continue;
+ }
+ }
+ }
+ ss << " " << sym << "\n";
+ }
+ ss << "-- \n" << message_;
+ message_ = ss.str();
+ free(symbols);
+}
+#endif
+
///////////////////////////////////////////////////////////////////////////
// senf::SystemException
prefix_ senf::Exception::Exception(std::string const & description)
: message_(description)
-{}
+{
+#ifdef SENF_DEBUG
+ addBacktrace();
+#endif
+}
prefix_ std::string const & senf::Exception::message()
const
struct FooException : public senf::Exception
{ FooException() : senf::Exception("Foo hit the fan") {} };
\endcode
+
+ If SENF is compiled in debug mode (SENF_DEBUG is defined), the exception message will
+ automatically include a stack backtrace. For this to work, you need to add the
+ <tt>-rdynamic</tt> option to all link commands. This feature depends on <tt>gcc</tt> and
+ the GNU-libc.
*/
namespace senf {
exceptions. */
private:
+#ifdef SENF_DEBUG
+ void addBacktrace();
+#endif
std::string message_;
};
catch (senf::SystemException & e) {
BOOST_CHECK_EQUAL( e.errorNumber(), ENOENT );
BOOST_CHECK_EQUAL( e.errorString(), "No such file or directory" );
- BOOST_CHECK_EQUAL( e.what(), "[No such file or directory] ::open()\nmore\nx=1\ny=2" );
+ std::string what (e.what());
+ std::string::size_type pos (what.find("-- \n"));
+ if (pos != std::string::npos)
+ what = std::string(what, pos+4);
+ BOOST_CHECK_EQUAL( what, "[No such file or directory] ::open()\nmore\nx=1\ny=2" );
}
}
# define SENF_SENFLOG_LIMIT senf::log::NOTICE
# endif
# endif
+#
+# ifndef SENF_DEBUG_BACKTRACE_NUMCALLERS
+# define SENF_DEBUG_BACKTRACE_NUMCALLERS 64
+# endif
#
# ///////////////////////////////hh.e////////////////////////////////////////
# endif
# CPPDEFINES = [ '_GLIBCXX_DEBUG' ],
env.Append(CXXFLAGS = [ '-O0', '-g', '-fno-inline' ],
CPPDEFINES = [ 'SENF_DEBUG' ],
- LINKFLAGS = [ '-g' ])
+ LINKFLAGS = [ '-g', '-rdynamic' ])
env.Append(CPPDEFINES = [ '$EXTRA_DEFINES' ],
LIBS = [ '$EXTRA_LIBS' ],