Files
mrw-cxx/mrw/autostacktracestderr.cpp

252 lines
9.2 KiB
C++
Raw Normal View History

/** @file
$Id$
$Date$
$Author$
@copy © Marc Wäckerlin
@license LGPL, see file <a href="license.html">COPYING</a>
*/
2004-04-21 06:39:20 +00:00
#include <mrw/stacktrace.hpp>
#include <mrw/exception.hpp>
2007-08-16 07:43:56 +00:00
#include <csignal>
2004-04-21 06:39:20 +00:00
#include <exception>
#include <iostream>
namespace mrw {
/** @addtogroup grpStackTrace */
2004-04-23 16:03:29 +00:00
//@{
/** @defgroup AutoTrace Automated Unexpected and Terminate Handler
with Stack Trace
2004-04-23 16:03:29 +00:00
@brief Don't care about the unexpected handler, don't care about
a try-catch in the main, let the library do all the repetitive
work for you.
2004-04-23 16:03:29 +00:00
For all your programs it is recommended to implement an
identical unexpected handler, that rethrows, catches the @c
2004-04-23 16:03:29 +00:00
mrw::exception, @c std::exception and all unknown exceptions,
traces them and finally quits with a throw of a @c
std::bad_exception. You are also required to write a @c try @c
catch block around all in your @c main, so that you don't miss
any exception. The only thing that may be different from project
to project is, how tracing is done. The MRW C++ Class Library
provides you with additional libraries you can link to. By
linking to the library, you get an unexpected handler and an
exception trace in the @c main for free: You don't need to add a
single line of code, just link to one more library! The
libraries differ in how tracing is done.
2004-04-23 16:03:29 +00:00
The Implementation is done with a static instance of a class that
sets the unexpected handler in the constructor.
@section trcstderr Trace using std::cerr
If you link to the library @c libmrwexcstderr using a linker
option such as: @c -lmrwexcstderr, then an unexpected and a
terminate handler are registered, that trace to the standard
2007-08-16 07:43:56 +00:00
error stream @c std::cerr. 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!
2004-04-23 16:03:29 +00:00
*/
//@{
/** @brief unexpected handler, that traces to @c std::cerr
The unexpected handler is installed automatically when you link
to @c -lmrwexcstderr. The implementation of this unexpected
handler is as follows:
@code
void unexpected_stderr() {
std::cerr<<"UNEXPECTED EXCEPTION: ----------------------------"<<std::endl;
try {
StackTrace::createSymtable();
2004-04-23 16:03:29 +00:00
throw;
} catch (const mrw::exception& x) {
std::cerr<<"---------- Reason:"<<std::endl
<<x.what()<<std::endl
<<"---------- Stack:"<<std::endl
2004-10-13 10:41:28 +00:00
<<x.stacktrace();
2004-04-23 16:03:29 +00:00
} catch (const std::exception& x) {
std::string st((std::string)StackTrace());
2004-04-23 16:03:29 +00:00
std::cerr<<"---------- Reason:"<<std::endl
<<x.what()<<std::endl
<<"---------- Stack: "<<std::endl<<st;
2004-04-23 16:03:29 +00:00
} catch (...) {
std::string st((std::string)StackTrace());
2004-04-23 16:03:29 +00:00
std::cerr<<"---------- Reason: **** not available ****"<<std::endl
<<"---------- Stack:"<<std::endl<<st;
2004-04-23 16:03:29 +00:00
}
std::cerr<<"-------------------------------------------------"<<std::endl;
throw std::bad_exception();
}
@endcode
*/
void unexpected_stderr() {
2004-04-21 06:39:20 +00:00
std::cerr<<"UNEXPECTED EXCEPTION: ----------------------------"<<std::endl;
try {
StackTrace::createSymtable();
throw;
} catch (const mrw::exception& x) {
std::cerr<<"---------- Reason:"<<std::endl
<<x.what()<<std::endl
<<"---------- Stack:"<<std::endl
<<x.stacktrace();
} catch (const std::exception& x) {
std::string st((std::string)StackTrace());
std::cerr<<"---------- Reason:"<<std::endl
<<x.what()<<std::endl
<<"---------- Stack:"<<std::endl<<st;
} catch (...) {
std::string st((std::string)StackTrace());
std::cerr<<"---------- Reason: **** not available ****"<<std::endl
<<"---------- Stack:"<<std::endl<<st;
}
std::cerr<<"-------------------------------------------------"<<std::endl;
throw std::bad_exception();
}
/** @brief terminate handler, that traces to @c std::cerr
The terminate handler is installed automatically when you link
to @c -lmrwexcstderr. The implementation of this terminate
handler is as follows:
@code
void terminate_stderr() {
std::cerr<<"UNCAUGHT EXCEPTION: ----------------------------"<<std::endl;
2004-04-21 06:39:20 +00:00
try {
throw;
} catch (const mrw::exception& x) {
StackTrace::createSymtable();
std::cerr<<"---------- Reason:"<<std::endl
<<x.what()<<std::endl
<<"---------- Stack:"<<std::endl
2004-10-13 10:41:28 +00:00
<<x.stacktrace();
2004-04-21 06:39:20 +00:00
} catch (const std::exception& x) {
std::cerr<<"---------- Reason:"<<std::endl
<<x.what()<<std::endl
<<"---------- Stack: **** not available ****"<<std::endl;
} catch (...) {
std::cerr<<"---------- Reason: **** not available ****"<<std::endl
<<"---------- Stack: **** not available ****"<<std::endl;
}
std::cerr<<"-------------------------------------------------"<<std::endl;
exit(1);
}
@endcode
*/
void terminate_stderr() {
std::cerr<<"UNCAUGHT EXCEPTION: ----------------------------"<<std::endl;
try {
throw;
} catch (const mrw::exception& x) {
StackTrace::createSymtable();
std::cerr<<"---------- Reason:"<<std::endl
<<x.what()<<std::endl
<<"---------- Stack:"<<std::endl
<<x.stacktrace();
} catch (const std::exception& x) {
std::cerr<<"---------- Reason:"<<std::endl
<<x.what()<<std::endl
<<"---------- Stack: **** not available ****"<<std::endl;
} catch (...) {
std::cerr<<"---------- Reason: **** not available ****"<<std::endl
<<"---------- Stack: **** not available ****"<<std::endl;
}
std::cerr<<"-------------------------------------------------"<<std::endl;
exit(1);
2004-04-21 06:39:20 +00:00
}
2007-08-16 07:43:56 +00:00
/** @brief segmentation-fault handler, that traces using stderr
The segmentation-fault handler is installed automatically when you link
to @c -lmrwexcstderr. The implementation of this handler is as follows:
@code
void signal_stderr(int sig) {
std::cerr<<"SIGNAL RECEIVED: -------------------------------"<<std::endl;
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());
stderr::LoggerPtr logger(stderr::Logger::getLogger(_T("mrw.stacktrace")));
std::cerr<<"---------- Reason:"<<std::endl
<<"Aborted by signal: "<<txt<<std::endl
<<"---------- Stack:"<<std::endl
<<st<<std::endl
<<"-------------------------------------------------"<<std::endl;
if (abort) exit(1);
}
@endcode
*/
void signal_stderr(int sig) {
std::cerr<<"SIGNAL RECEIVED: -------------------------------"<<std::endl;
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());
std::cerr<<"---------- Reason:"<<std::endl
<<"Aborted by signal: "<<txt<<std::endl
<<"---------- Stack:"<<std::endl
<<st<<std::endl
<<"-------------------------------------------------"<<std::endl;
if (abort) exit(1);
}
2004-04-23 16:03:29 +00:00
//@}
//@}
2004-04-21 06:39:20 +00:00
class AutoStackTrace {
public:
AutoStackTrace() {
2004-04-23 16:03:29 +00:00
std::set_unexpected(&mrw::unexpected_stderr);
std::set_terminate(&mrw::terminate_stderr);
2007-08-16 07:43:56 +00:00
std::signal(SIGFPE, &mrw::signal_stderr);
std::signal(SIGILL, &mrw::signal_stderr);
std::signal(SIGSEGV, &mrw::signal_stderr);
std::signal(SIGBUS, &mrw::signal_stderr);
std::signal(SIGIOT, &mrw::signal_stderr);
std::signal(SIGTRAP, &mrw::signal_stderr);
std::signal(SIGSYS, &mrw::signal_stderr);
2004-04-21 06:39:20 +00:00
}
};
// initialize stack traces (load symbols)
static AutoStackTrace _autoStackTrace;
}