/** @file
$ Id $
$ Date $
$ Author $
@ copy & copy ; Marc W & auml ; ckerlin
@ license LGPL , see file < a href = " license.html " > COPYING < / a >
*/
# include <mrw/stacktrace.hpp>
# include <mrw/exception.hpp>
# include <csignal>
# include <exception>
# include <log4cxx/logger.h>
// support for log4cxx 0.9.7 and for new CVS version
# ifndef LOG4CXX_LOCATION
# define MRW_LOG4CXX_LOCATION __FILE__, __LINE__
# define MRW_LEVEL_DEBUG ::log4cxx::Level::DEBUG
# define MRW_LEVEL_INFO ::log4cxx::Level::INFO
# define MRW_LEVEL_WARN ::log4cxx::Level::WARN
# define MRW_LEVEL_ERROR ::log4cxx::Level::ERROR
# define MRW_LEVEL_FATAL ::log4cxx::Level::FATAL
# else
# define LOG4CXX_CVS
# define MRW_LOG4CXX_LOCATION \
: : log4cxx : : spi : : LocationInfo ( __FILE__ , __FUNCTION__ , __LINE__ )
# define MRW_LEVEL_DEBUG ::log4cxx::Level::getDebug()
# define MRW_LEVEL_INFO ::log4cxx::Level::getInfo()
# define MRW_LEVEL_WARN ::log4cxx::Level::getWarn()
# define MRW_LEVEL_ERROR ::log4cxx::Level::getError()
# define MRW_LEVEL_FATAL ::log4cxx::Level::getFatal()
# endif
namespace mrw {
/** @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 . Also for all know signals there ' s a signal
handler to trace the stack before termination ( except in case of
a @ c SIGTRAP , wehere the program is not terminated ) . 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 ( ) . @ see @ ref AutoInitLog4cxx if you also want to
automatically configure @ c log4cxx .
*/
//@{
/** @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 ( " mrw.stacktrace " ) ) ;
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 ( )
+ " \n Stack:+ \n " + x . stacktrace ( ) ) ;
} catch ( const std : : exception & x ) {
logger - > fatal ( std : : string ( " Reason: \n " ) + x . what ( )
+ " \n Stack: \n " + st ) ;
} catch ( . . . ) {
logger - > fatal ( std : : string ( " Reason: **** not available **** " )
+ " \n Stack: \n " + st ) ;
}
throw std : : bad_exception ( ) ;
}
@ endcode
*/
void unexpected_log4cxx ( ) {
static const std : : string name ( " mrw.stacktrace " ) ;
log4cxx : : LoggerPtr logger
( log4cxx : : Logger : : getLogger ( log4cxx : : String ( name . begin ( ) , name . end ( ) ) ) ) ;
static const std : : string txt ( " Unexpected Exception " ) ;
logger - > fatal ( log4cxx : : String ( txt . begin ( ) , txt . end ( ) ) , MRW_LOG4CXX_LOCATION ) ;
StackTrace : : createSymtable ( ) ;
std : : string st ( ( std : : string ) StackTrace ( ) ) ;
try {
throw ;
} catch ( const mrw : : exception & x ) {
std : : string txt ( std : : string ( " Reason: \n " ) + x . what ( )
+ " \n Stack: \n " + x . stacktrace ( ) ) ;
logger - > fatal ( log4cxx : : String ( txt . begin ( ) , txt . end ( ) ) ) ;
} catch ( const std : : exception & x ) {
std : : string txt ( std : : string ( " Reason: \n " ) + x . what ( )
+ " \n Stack: \n " + st ) ;
logger - > fatal ( log4cxx : : String ( txt . begin ( ) , txt . end ( ) ) ) ;
} catch ( . . . ) {
std : : string txt ( std : : string ( " Reason: **** not available **** " )
+ " \n Stack: \n " + st ) ;
logger - > fatal ( log4cxx : : String ( txt . begin ( ) , txt . end ( ) ) ) ;
}
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 ( " mrw.stacktrace " ) ) ;
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 ( )
+ " \n Stack:+ \n " + x . stacktrace ( ) ) ;
} catch ( const std : : exception & x ) {
logger - > fatal ( std : : string ( " Reason: \n " ) + x . what ( )
+ " \n Stack: \n " + st ) ;
} catch ( . . . ) {
logger - > fatal ( std : : string ( " Reason: **** not available **** " )
+ " \n Stack: \n " + st ) ;
}
exit ( 1 ) ;
}
@ endcode
*/
void terminate_log4cxx ( ) {
static const std : : string name ( " mrw.stacktrace " ) ;
log4cxx : : LoggerPtr logger
( log4cxx : : Logger : : getLogger ( log4cxx : : String ( name . begin ( ) , name . end ( ) ) ) ) ;
static const std : : string txt ( " Uncaught Exception " ) ;
logger - > fatal ( log4cxx : : String ( txt . begin ( ) , txt . end ( ) ) , MRW_LOG4CXX_LOCATION ) ;
StackTrace : : createSymtable ( ) ;
std : : string st ( ( std : : string ) StackTrace ( ) ) ;
try {
throw ;
} catch ( const mrw : : exception & x ) {
std : : string txt ( std : : string ( " Reason: \n " ) + x . what ( )
+ " \n Stack: \n " + x . stacktrace ( ) ) ;
logger - > fatal ( log4cxx : : String ( txt . begin ( ) , txt . end ( ) ) ) ;
} catch ( const std : : exception & x ) {
std : : string txt ( std : : string ( " Reason: \n " ) + x . what ( )
+ " \n Stack: \n " + st ) ;
logger - > fatal ( log4cxx : : String ( txt . begin ( ) , txt . end ( ) ) ) ;
} catch ( . . . ) {
std : : string txt ( std : : string ( " Reason: **** not available **** " )
+ " \n Stack: \n " + st ) ;
logger - > fatal ( log4cxx : : String ( txt . begin ( ) , txt . end ( ) ) ) ;
}
exit ( 1 ) ;
}
/** @brief segmentation-fault handler, that traces using log4cxx
The segmentation - fault handler is installed automatically when you link
to @ c - lmrwexclog4cxx . The implementation of this handler is as follows :
@ code
void signal_log4cxx ( int sig ) {
std : : string txt ;
bool abort ( true ) ;
switch sig {
case SIGFPE : txt = " SIGFPE: Arithmetic error. " ; break ;
case SIGILL : txt = " SIGILL: Illegal instruction. " ; break ;
case SIGSEGV : txt = " SIGSEGV: Segmentation fault "
" (invalid access to valid memory). " ; break ;
case SIGBUS : txt = " SIGBUS: Invalid pointer dereference "
" (access to an invalid memory address). " ; break ;
case SIGABRT : txt = " SIGABRT: Funktion 'abort' was called. " ; break ;
case SIGIOT : txt = " SIGIOT: PDP-11 'iot' instruction " ; break ;
case SIGTRAP : txt = " SIGTRAP: Breakpoint instruction. " ; abort = false ; break ;
case SIGEMT : txt = " SIGEMT: Emulator trap. " ; break ;
case SIGSYS : txt = " SIGSYS: Bad system call. " ; break ;
default : txt = " Unknown Signal Nr. " + sig ; break ;
}
StackTrace : : createSymtable ( ) ;
std : : string st ( ( std : : string ) StackTrace ( ) ) ;
log4cxx : : LoggerPtr logger ( log4cxx : : Logger : : getLogger ( " mrw.stacktrace " ) ) ;
logger - > fatal ( " Aborted by signal: " + txt + " \n Stack: \n " + st ) ;
if ( abort ) exit ( 1 ) ;
}
@ endcode
*/
void signal_log4cxx ( int sig ) {
std : : string txt ;
bool abort ( true ) ;
switch ( sig ) {
case SIGFPE : txt = " SIGFPE: Arithmetic error. " ; break ;
case SIGILL : txt = " SIGILL: Illegal instruction. " ; break ;
case SIGSEGV : txt = " SIGSEGV: Segmentation fault "
" (invalid access to valid memory). " ; break ;
case SIGBUS : txt = " SIGBUS: Invalid pointer dereference "
" (access to an invalid memory address). " ; break ;
case SIGABRT : txt = " SIGABRT: Funktion 'abort' was called. " ; break ;
case SIGTRAP : txt = " SIGTRAP: Breakpoint instruction. " ; abort = false ; break ;
case SIGSYS : txt = " SIGSYS: Bad system call. " ; break ;
default : txt = " Unknown Signal Nr. " + sig ; break ;
}
StackTrace : : createSymtable ( ) ;
std : : string st ( ( std : : string ) StackTrace ( ) ) ;
static const std : : string name ( " mrw.stacktrace " ) ;
log4cxx : : LoggerPtr logger
( log4cxx : : Logger : : getLogger ( log4cxx : : String ( name . begin ( ) , name . end ( ) ) ) ) ;
std : : string errtxt ( " Aborted by signal: " + txt + " \n Stack: \n " + st ) ;
logger - > fatal ( log4cxx : : String ( errtxt . begin ( ) , errtxt . end ( ) ) ) ;
if ( abort ) exit ( 1 ) ;
}
class AutoStackTrace {
public :
AutoStackTrace ( ) {
std : : set_unexpected ( & mrw : : unexpected_log4cxx ) ;
std : : set_terminate ( & mrw : : terminate_log4cxx ) ;
std : : signal ( SIGFPE , & mrw : : signal_log4cxx ) ;
std : : signal ( SIGILL , & mrw : : signal_log4cxx ) ;
std : : signal ( SIGSEGV , & mrw : : signal_log4cxx ) ;
std : : signal ( SIGBUS , & mrw : : signal_log4cxx ) ;
std : : signal ( SIGTRAP , & mrw : : signal_log4cxx ) ;
std : : signal ( SIGSYS , & mrw : : signal_log4cxx ) ;
}
} ;
//@}
// initialize stack traces (load symbols)
static AutoStackTrace _autoStackTrace ;
}