自学内容网 自学内容网

ubuntu在代码中添加异常信号捕获防止异常退出(可用于多线程程序)

1.异常信号捕获:

在代码运行处理大批量数据时,往往不想因为某一个数据的文件损坏或异常导致代码的运行退出或异常重启,影响系统运行的稳定性。而这些异常又不能够被try catch捕获到,因此在某些特殊应用中,需要进行异常信号的捕获,如SIGSEGV信号、SIGABRT 信号。这些异常信号的捕获在单线程中往往很容易实现,但在复杂的项目中往往需要多个线程,若想实现单个线程只捕获自己线程内的异常,并继续处理的功能,需要对信号进行分隔开,防止串线程,导致程序的意外退出。以下是代码实现示例:

#include <csignal>
#include <cstdlib>
#include <csetjmp>

thread_local JumpBuffer jumpBuffer_thread_1;
thread_local JumpBuffer jumpBuffer_thread_2;

void signalHandlerThread1(int signal, siginfo_t *info, void *context) {
    std::cerr << "Caught signal " << signal << " (segmentation fault)" << std::endl;
    std::cerr << "Signal origin: " << info->si_addr << std::endl;
    // 恢复执行到上次设置的跳转点
    siglongjmp(jumpBuffer.get(), 1);
}

void setupSignalHandlerThread1() {
    struct sigaction sa{};
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = signalHandlerThread1;
    // 注册信号处理函数(目前只捕获了(SIGABRT)6和(SIGSEGV)11两种信号)
    if (sigaction(SIGSEGV, &sa, nullptr) == -1) {
        std::cerr << "线程1,Failed to set signal handler" << std::endl;
    }else if(sigaction(SIGABRT , &sa, nullptr) == -1){
        std::cerr << "线程1,Failed to set signal handler" << std::endl;
    }
    // add others signal
}

// cxy20240713 异常信号捕获,出现异常时不要退出程序,继续执行(只捕获引擎检测线程的信号)
void signalHandlerThread2(int signal, siginfo_t *info, void *context) {
    std::cerr << "Caught signal " << signal << " (segmentation fault)" << std::endl;
    std::cerr << "Signal origin: " << info->si_addr << std::endl;
    // 恢复执行到上次设置的跳转点
    siglongjmp(jumpBuffer_engine.get(), 1);
}

void setupSignalHandlerThread2() {
    struct sigaction sa{};
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = signalHandlerThread2;

    // 注册信号处理函数(目前只捕获了(SIGABRT)6和(SIGSEGV)11两种信号)
    if (sigaction(SIGSEGV, &sa, nullptr) == -1) {
        std::cerr << "线程2,Failed to set signal handler" << std::endl;
    }else if(sigaction(SIGABRT , &sa, nullptr) == -1){
        std::cerr << "线程2,Failed to set signal handler" << std::endl;
    }
    // add others signal
}

void function1()
{
// process1
setupSignalHandlerThread1();
if(sigsetjmp(jumpBuffer_thread_1.get(), 1) == 0){
function1_process();
}

}

void function2()
{
// process2
setupSignalHandlerThread2();
if(sigsetjmp(jumpBuffer_thread_2.get(), 1) == 0){
function2_process();
}
}


int main()
{
std::thread Handler1(function1);    //线程1
    std::thread Handler2(function2);    //线程2
    //other process ...
    Handler1.join();      
    Handler1.join();              
    return 0;
}

上述代码分别在两个线程中捕获了各自线程的异常信号,并在捕获到异常时,程序的运行跳转到指定的位置,即setupSignalHandlerThread1();setupSignalHandlerThread2();函数位置,进行继续运行。


原文地址:https://blog.csdn.net/qq_43685921/article/details/140485984

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!