为SIGSEGV注册信号处理程序,并且仍然能够从操作系统创建完整的崩溃转储



我们使用的标准模式是用sigaction为SIGSEGV注册自定义信号处理程序,然后当出现分段错误时,使用回溯函数遍历堆栈并将其打印到某个文件。在日志中有回溯是一个很好的功能,但它禁止操作系统写入崩溃程序的完整转储,这非常有用。如何既能捕获SIGSEGV,进行自定义处理,又能让操作系统像默认操作那样创建完整转储?

例如,我可以调用记住指向默认处理程序的oldact指针(如man中所述(,然后直接从自定义处理程序中调用它吗?不用说,我们需要崩溃来表明它发生的确切地点。因此,例如,将处理程序重新注册到旧值并在其他地方隐式地崩溃程序是行不通的。

您可以在处理完信号后重置sigaction。然后,出错指令将在从处理程序返回后重新运行,并再次出错,导致核心转储。

这里有一个例子:

#include <signal.h>
#include <unistd.h>
struct sigaction oldSA;
void handler(int signal)
{
const char msg[] = "Caught, should dump core nown";
write(STDERR_FILENO, msg, sizeof msg - 1);
sigaction(SIGSEGV, &oldSA, NULL);
}
int main()
{
struct sigaction sa={0};
sa.sa_handler=handler;
sigaction(SIGSEGV, &sa, &oldSA);
int* volatile p=NULL;
*p=5; // cause segfault
}

示例运行:

$ gcc test.c -o test && ./test
Caught, should dump core now
Segmentation fault (core dumped)

最新更新