我已经多次谷歌为信号处理程序中的backtrace()找到正确的解决方案,并尝试了几乎所有的东西,但我无法在我的信号处理程序中成功获得回溯 – 这不是SIGUSR1处理程序.

在uclibc config中启用UCLIBC\_HAS\_BACKTRACE = y并编译它
验证了libubacktrace.so已创建
使用以下选项编译我的应用程序二进制文件
-G
-rdynamic
-fexception或-funwind-tables
二进制本身似乎被“剥离”

但是,我无法从信号处理程序中获得完整的回溯.
只打印了我在信号处理程序中调用的函数地址.

如果我使用target-gdb二进制文件并使用gdb –pid命令附加进程,我就可以正确地获得完整的回溯.

另外,我试过pstack但是(pstack-1.2 – 尝试了手臂补丁,但它很可怕……没有打印)不是很有帮助.


有什么建议?

1)Makefile中的编译器选项

CFLAGS = -g -fexceptions -funwind-tables -Werror $(WARN)…

2)代码

代码非常简单.

#define CALLSTACK_SIZE 10

static void print_stack(void) {
    int i, nptrs;
    void *buf[CALLSTACK_SIZE + 1];
    char **strings;

    nptrs = backtrace(buf, CALLSTACK_SIZE);
    printf("%s: backtrace() returned %d addresses\n", __func__, nptrs);

    strings = backtrace_symbols(buf, nptrs);

    if(strings == NULL) {
        printf("%s: no backtrace captured\n", __func__);
        return;
    }

    for(i = 0; i < nptrs; i++) {
        printf("%s\n", strings[i]);
    }

    free(strings);
}

...
static void sigHandler(int signum)
{
    printf("%s: signal %d\n", __FUNCTION__, signum);
    switch(signum ) {
    case SIGUSR2:
        // told to quit
        print_stack();
        break;
    default:
        break;
    }
}

解决方法:

仔细阅读signal(7)signal-safety(7).

信号处理程序仅限于(直接或间接)调用异步信号安全功能(实际上,仅大多数syscalls(2))和backtrace(3)甚至printf(3)malloc(3)或免费不是异步信号安全.所以你的代码是不正确的:信号处理程序sigHandler正在调用printf并间接(通过print\_stack)释放它们并且它们不是异步信号安全的.

因此,您唯一的选择是使用gdb调试器.

了解更多关于POSIX signal.h&实际上,信号处理程序可以做的几乎唯一合理的事情是设置一些全局,线程局部或静态易失性sig\_atomic\_t flag,必须在别处进行测试.它也可以直接write(2)pipe(7)的几个字节,你的应用程序将在别处读取(例如,在它的事件循环中,如果它是一个GUI应用程序).

您也可以使用Ian Taylor的libbacktrace from inside GCC(假设您的程序使用调试信息编译,例如使用-g).它不能保证在信号处理程序中工作(因为它不仅仅使用异步信号安全功能),但它实际上非常有用.

请注意,内核在处理信号时为sigreturn(2)设置了一个调用帧(在call stack中).

您也可以使用(特别是如果您的应用程序是单线程的)sigaltstack(2)具有备用信号堆栈.我不确定它会有所帮助.

如果您有事件循环,则可以考虑使用特定于Linux的signalfd(2)并请求您的事件循环轮询它.对于SIGTERM或SIGQUIT或SIGALRM,这是一个非常有用的技巧.

标签: linux, arm, uclibc

相关文章推荐

添加新评论,含*的栏目为必填