第二次无法捕获分段错误

Lig*_*ith 2 c++ linux segmentation-fault

我试图在发生分段错误时重新启动程序。

我有以下最小的可重现代码:-

#include <csignal>
#include <unistd.h>
#include <iostream>

int app();

void ouch(int sig) {
    std::cout << "got signal " << sig << std::endl;
    exit(app());
}

struct L { int l; };
static int i = 0;

int app() {
    L *l= nullptr;
    while(1) {
        std::cout << ++i << std::endl;
        sleep(1);
        std::cout << l->l << std::endl; //crash
        std::cout << "Ok" << std::endl;
    }
}

int main() {
    struct sigaction act;
    act.sa_handler = ouch;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    sigaction(SIGKILL, &act, 0);
    sigaction(SIGSEGV, &act, 0);
    return app();
}

Run Code Online (Sandbox Code Playgroud)

它第一次成功捕获 sigsegv 但在打印 2 后,它向我显示分段错误(核心已转储)

1
got signal 11
2
zsh: segmentation fault (core dumped)  ./a.out
Run Code Online (Sandbox Code Playgroud)

在 ArchLinux 上使用 clang 12.0.1 和 gcc 11.1.0 进行测试

这是操作系统特定的行为还是我的代码有问题

G. *_*pen 6

问题是,当您通过exit(app())从 inside调用重新启动程序时ouch(),从技术上讲您仍然位于信号处理程序内部。信号处理程序将被阻塞,直到您从它返回为止。由于您再也没有回来,因此您无法捕获第二个 SIGSEGV。

如果您收到 SIGSEGV,则表明发生了非常糟糕的事情,并且不能保证您可以通过app()再次调用来“重新启动”进程。处理此问题的最佳解决方案是让另一个程序启动您的程序,并在崩溃时重新启动它。有关如何处理此问题的一些建议,请参阅此 ServerFault 问题。