/** @file $Id$ $Date$ $Author$ @copy © Marc Wäckerlin @license LGPL, see file COPYING $Log$ Revision 1.5 2005/01/28 12:13:11 marc interference between group name StackTrace and class name StackTrace Revision 1.4 2005/01/28 12:13:11 marc interference between group name StackTrace and class name StackTrace Revision 1.3 2005/01/28 07:42:23 marc added terminate handler (uncaught handler) Revision 1.2 2004/08/28 16:21:25 marc mrw-c++-0.92 (mrw) - new file: version.cpp - new file header for all sources - work around warning in mrw::auto - possibility to compile without log4cxx - work around bugs in demangle.h and libiberty.h - corrections in documentation - added simple tracing mechanism - more warnings - small corrections in Auto<>::Free and a new test for it - possibility to compile without stack trace */ #include #include #include #include namespace mrw { /** @addtogroup grpStackTrace */ //@{ /** @addtogroup AutoTrace @section trclog4cxx Trace using the log4cxx Library If you link to the library @c libmrwexclog4cxx using a linker option such as: @c -lmrwexclog4cxx, then an unexpected and a terminate handler are registered, that trace a fatal error using the log4cxx library. You don't need to change a single line in your code! The log4cxx library is located at: - http://logging.apache.org/log4cxx @note The configurator is not installed automatically. If you want to trace e.g. on the console, you have to call @c log4cxx::BasicConfigurator::configure(); as first statement in your @c main(). */ //@{ /** @brief unexpected handler, that traces using log4cxx The unexpected handler is installed automatically when you link to @c -lmrwexclog4cxx. The implementation of this unexpected handler is as follows: @code void unexpected_log4cxx() { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(_T("libmrw")); logger->fatal("Unexpected Exception", __FILE__, __LINE__); StackTrace::createSymtable(); std::string st((std::string)StackTrace()); try { throw; } catch (const mrw::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() +"\nStack:+\n"+x.stacktrace()); } catch (const std::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() +"\nStack:\n"+st); } catch (...) { logger->fatal(std::string("Reason: **** not available ****") +"\nStack:\n"+st); } throw std::bad_exception(); } @endcode */ void unexpected_log4cxx() { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(_T("libmrw")); logger->fatal("Unexpected Exception", __FILE__, __LINE__); StackTrace::createSymtable(); std::string st((std::string)StackTrace()); try { throw; } catch (const mrw::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() +"\nStack:\n"+x.stacktrace()); } catch (const std::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() +"\nStack:\n"+st); } catch (...) { logger->fatal(std::string("Reason: **** not available ****") +"\nStack:\n"+st); } throw std::bad_exception(); } /** @brief terminate handler, that traces using log4cxx The terminate handler is installed automatically when you link to @c -lmrwexclog4cxx. The implementation of this terminate handler is as follows: @code void terminate_log4cxx() { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(_T("libmrw")); logger->fatal("Uncaught Exception", __FILE__, __LINE__); StackTrace::createSymtable(); std::string st((std::string)StackTrace()); try { throw; exit(0); } catch (const mrw::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() +"\nStack:+\n"+x.stacktrace()); } catch (const std::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() +"\nStack:\n"+st); } catch (...) { logger->fatal(std::string("Reason: **** not available ****") +"\nStack:\n"+st); } exit(1); } @endcode */ void terminate_log4cxx() { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(_T("libmrw")); logger->fatal("Uncaught Exception", __FILE__, __LINE__); StackTrace::createSymtable(); std::string st((std::string)StackTrace()); try { throw; } catch (const mrw::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() +"\nStack:\n"+x.stacktrace()); } catch (const std::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() +"\nStack:\n"+st); } catch (...) { logger->fatal(std::string("Reason: **** not available ****") +"\nStack:\n"+st); } exit(1); } //@} //@} class AutoStackTrace { public: AutoStackTrace() { std::set_unexpected(&mrw::unexpected_log4cxx); std::set_terminate(&mrw::terminate_log4cxx); } }; // initialize stack traces (load symbols) static AutoStackTrace _autoStackTrace; }