在开发中,经常会使用第三方库或SDK接口,以达到为我所用的效果;但是无法预估接口的具体细节,经常抛出异常、退出(例如abort)
#include<setjmp.h>
#include<signal.h>
jmp_buf env;
void signal_hander_fun(int signal_num)
{
XMLLogger::getInstance()->writeLogUrl("OES_SDK_ERROR", QStringList() << u8"错误信号码:" + QString::number(signal_num));
longjmp(env, 2);
}
namespace {
#ifdef Q_OS_WIN
typedef void (*SigHander)(int);
#else
typedef __sighandler_t SigHander;
#endif
class SignalCapture
{
public:
explicit SignalCapture()
{
_sigSegvHandler = signal(SIGSEGV, signal_hander_fun);
_sigAbrtHandler = signal(SIGABRT, signal_hander_fun);
_sigIntHandler = signal(SIGINT, signal_hander_fun);
_sigIllHandler = signal(SIGILL, signal_hander_fun);
_sigFpeHandler = signal(SIGFPE, signal_hander_fun);
_sigTermHandler = signal(SIGTERM, signal_hander_fun);
#ifdef Q_OS_LINUX
_sigBusHandler = signal(SIGBUS, signal_hander_fun);
_sigQuitHandler = signal(SIGQUIT, signal_hander_fun);
#else
_sigBrkHandler = signal(SIGBREAK, signal_hander_fun);
_sigAbrtCompatHandler = signal(SIGABRT_COMPAT, signal_hander_fun);
#endif
}
virtual ~SignalCapture()
{
signal(SIGSEGV, _sigSegvHandler);
signal(SIGABRT, _sigAbrtHandler);
signal(SIGINT, _sigIntHandler);
signal(SIGILL, _sigIllHandler);
signal(SIGFPE, _sigFpeHandler);
signal(SIGTERM, _sigTermHandler);
#ifdef Q_OS_LINUX
signal(SIGBUS, _sigBusHandler);
signal(SIGQUIT, _sigQuitHandler);
#else
signal(SIGBREAK, _sigBrkHandler);
signal(SIGABRT_COMPAT, _sigAbrtCompatHandler);
#endif
}
private:
SigHander _sigSegvHandler;
SigHander _sigAbrtHandler;
SigHander _sigIntHandler;
SigHander _sigIllHandler;
SigHander _sigFpeHandler;
SigHander _sigTermHandler;
#ifdef Q_OS_LINUX
SigHander _sigBusHandler;
SigHander _sigQuitHandler;
#else
SigHander _sigBrkHandler;
SigHander _sigAbrtCompatHandler;
#endif
};
template<typename Callable, typename... Args>
int tryCall(Callable fun, Args&&... args)
{
int ret = OES_SDK_ERROR;
SignalCapture sigCapture;
if(setjmp(env) != 0)
return OES_SDK_ERROR;
try
{
ret = fun(std::forward<Args>(args)...);
}
catch(...)
{
}
return ret;
}
通过tryCall模板函数可以捕捉异常退出的信号。