信号处理程序中的回溯

Backtrace inside Signal Handler

本文关键字:回溯 程序 信号处理      更新时间:2023-10-16

我正在尝试遵循这篇文章中的代码,让信号处理程序打印浮点和分段错误等错误的回溯。我使用 seg 故障信号作为起点。这是代码:

#include <cstdlib>      //for exit()
#include <signal.h>     //signal handling   
#include <execinfo.h>   //backtrace, backtrace_symbols and backtrace_fd
#include <iostream>
#include <string.h>
#include <stdio.h>
#define TRACE_MSG fprintf(stderr, "TRACE at: %s() [%s:%d]n", 
        __FUNCTION__, __FILE__, __LINE__)
void show_stackframe()
{
    void *trace[1024];
    char **messages = (char **) NULL;
    int i, trace_size = 0;
    TRACE_MSG;
    trace_size = backtrace(trace, 1024);    // segfault here???
    // More code here to print backtrace, but not needed at the moment..
    TRACE_MSG;
}
void sigSegvHandler( int signum, siginfo_t* info, void* arg )
{
    TRACE_MSG;
    show_stackframe();
    return;
}
double func_b()
{
    show_stackframe();  // Show that backtrace works without being 
                    // called inside sighandler.
    TRACE_MSG;
    int int_a[5];
    int_a[0] = 4;
    int_a[11] = 10;         // cause a segfault on purpose to see
                    // how the signal handling performs.
    return 1.1;
}
int main()
{
    // Examine and change the seg fault signal
    struct sigaction segvAction;   // File: /usr/include/bits/sigaction.h
   // Initialize segvAction struct to all zeros for initialiation
   memset( &segvAction,  0, sizeof( segvAction ) );
   segvAction.sa_sigaction = sigSegvHandler;
   segvAction.sa_flags = SA_SIGINFO;    //Invoke signal catching function with 3 arguments instead of 1
   // Set the action for the SIGSEGV signal
   sigaction( SIGSEGV, &segvAction,  NULL );
   func_b();    // Produce a SIGSEGV error
}

我正在使用:

 g++ -rdynamic testprogram.cpp -o testprogram

我从程序收到以下输出:

TRACE at: show_stackframe() [stackoverflow.cpp:15]
TRACE at: show_stackframe() [stackoverflow.cpp:17]
TRACE at: func_b() [stackoverflow.cpp:33]
TRACE at: sigSegvHandler() [stackoverflow.cpp:22]
TRACE at: show_stackframe() [stackoverflow.cpp:15]
Segmentation fault

我的问题是为什么 show_stackframe() 在 sigaction 内部导致分段错误,但不在 sigaction 处理程序内部时工作正常?我显然似乎设置了不正确的信号处理程序/操作,但我一整天都找不到它。在这种情况下,GDB 似乎没有任何帮助。

如此处所述,backtrace函数是 AS-Unsafe,这意味着从异步信号处理程序调用是不安全的。 这样做会调用未定义的行为。