/* 信号异常处理; by dzj, 09.08.14 ref:http://www.ibm.com/developerworks/cn/linux/l-cppexcep.html 'linux下c++异常处理技巧' disclosed anonymously 'method for extended c++ exception features to handle OS signal exceptions' 'unix 环境高级编程'.sigsetjmp&siglongjmp */ #ifndef DS_SIG_EXCEPT #define DS_SIG_EXCEPT #ifndef WIN32 #include #endif //WIN32 #include #include #include "../dslock.h" #include "../buflog.h" using namespace std; //#ifndef WIN32 //#include ////static sigjmp_buf* g_pJmpbuf = NULL;//全局跳转缓存; ////static volatile sig_atomic_t canjmp; //#endif //WIN32 //主干版本不使用,#define USE_SIG_TRY //使用信号转异常处理; #define USE_SIG_TRY //主干也开开,效率比原来更高点,也充分测试下这些异常处理代码,by dzj, 09.10.15; #ifdef USE_SIG_TRY extern bool g_isException; #ifdef WIN32 #define DS_TRY_BEGIN { try { #else //WIN32 #define DS_TRY_BEGIN \ { \ sigjmp_buf* oldjmpbuf = NULL; bool isoldbufvalid = false;\ GET_TLS_SIGEXCEPTBUF( oldjmpbuf, isoldbufvalid ); \ if ( !isoldbufvalid )\ {\ printf( "DS_TRY_BEGIN, invalid oldjumpbuf\n" );\ while(true);/*不可能错误, by dzj, 10.04.01*/\ }\ sigjmp_buf* newjmpbuf = new sigjmp_buf[sizeof(sigjmp_buf)/sizeof(__jmp_buf_tag)]; bool isnewbufset = false; \ SET_TLS_SIGEXCEPTBUF( newjmpbuf, isnewbufset );\ if ( !isnewbufset )\ {\ printf( "DS_TRY_BEGIN, can not set newjmpbuf\n" );\ while(true);/*不可能错误, by dzj, 10.04.01*/\ }\ try { \ int jmprst = sigsetjmp( *newjmpbuf, 1/*restore signal mask*/ ); \ if ( 0 != jmprst ) \ { \ /*使用buflog,buflog中不使用信号异常捕捉,cout << "return from signal handle, rst : "<< jmprst << endl; 从信号处理函数中longjump回来;*/\ NewLog( LOG_LEV_ERROR, "return from signal handle, : %d", jmprst );\ throw jmprst; \ } #endif //WIN32 #define DS_CATCH_SIG \ } catch ( int signalid ) { \ /*使用buflog,buflog中不使用信号异常捕捉,cout << "catch by sigsetjmp, signal:" << signalid << endl; */\ NewLog( LOG_LEV_ERROR, "catch by sigsetjmp, signal: %d", signalid );\ g_isException = true; #define DS_CATCH_NORMAL \ } catch (...) { \ /*使用buflog,buflog中不使用信号异常捕捉,cout << "exception catched!" << endl;*/\ NewLog( LOG_LEV_ERROR, "exception catched!" );\ g_isException = true; #ifdef WIN32 #define DS_END_TRY \ }\ } #else //WIN32 #define DS_END_TRY \ }\ bool isoldbufset = false;\ SET_TLS_SIGEXCEPTBUF( oldjmpbuf, isoldbufset );\ if ( !isoldbufset )\ {\ printf( "DS_END_TRY, can not set oldjmpbuf\n" );\ while(true);/*不可能错误, by dzj, 10.04.01*/\ }\ delete [] newjmpbuf; newjmpbuf = NULL; \ } #endif //WIN32 #define ST_SIG_CATCH DS_TRY_BEGIN { #define END_SIG_CATCH \ } DS_CATCH_SIG { \ NewLog( LOG_LEV_DEBUG, "DS_CATCH_SIG" );\ } DS_CATCH_NORMAL {\ NewLog( LOG_LEV_DEBUG, "DS_CATCH_NORMAL" );\ } DS_END_TRY; #else //USE_SIG_TRY #define DS_TRY_BEGIN #define DS_CATCH_SIG #define DS_CATCH_NORMAL #define DS_END_TRY #define ST_SIG_CATCH #define END_SIG_CATCH #endif //USE_SIG_TRY class ExceptionTracer { public: ExceptionTracer() { #ifndef WIN32 void* array1[25]; int nSize = backtrace( array1, 25 ); char** symbols = backtrace_symbols( array1, nSize); for ( int i=0; i class SignalTranslator { private: class SingleTonTranslator { public: SingleTonTranslator() { signal( SignalExceptionClass::GetSignalNumber(), SignalHandler ); } static void SignalHandler( int signo ) { //使用buflog,buflog中不使用信号异常捕捉,cout << "in SignalHandler:" << signo << endl; NewLog( LOG_LEV_ERROR, "in SignalHandler : %d", signo ); #ifdef WIN32 throw SignalExceptionClass(); #else //WIN32 { void* array1[25]; int nSize = backtrace( array1, 25 ); char** symbols = backtrace_symbols( array1, nSize); for ( int i=0; i g_objSegmentationFaultTranslator; class AbortSig : public ExceptionTracer, public exception { public: static inline int GetSignalNumber() { return SIGABRT; } }; extern SignalTranslator g_objAbortSigTranslator; #ifndef WIN32 class BusFault : public ExceptionTracer, public exception { public: static inline int GetSignalNumber() { return SIGBUS; } }; extern SignalTranslator g_objBusFaultTranslator; #endif //WIN32 class FloatingPointException : public ExceptionTracer, public exception { public: static inline int GetSignalNumber() { return SIGFPE; } }; extern SignalTranslator g_objFloatingPointExceptionTranslator; #endif //DS_SIG_EXCEPT