linux – 如何在进程信号处理程序(armv7-uclibc)中获得适当的回溯?

linux – 如何在进程信号处理程序(armv7-uclibc)中获得适当的回溯?,第1张

概述我已经多次谷歌为信号处理程序中的backtrace()找到正确的解决方案,并尝试了几乎所有的东西,但我无法在我的信号处理程序中成功获得回溯 – 这不是SIGUSR1处理程序. >在uclibc config中启用UCLIBC_HAS_BACKTRACE = y并编译它 >验证了libubacktrace.so已创建 >使用以下选项编译我的应用程序二进制文件 -G -rdynamic -fexcep 我已经多次谷歌为信号处理程序中的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 10static 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 – 如何在进程信号处理程序(armv7-uclibc)中获得适当的回溯?全部内容,希望文章能够帮你解决linux – 如何在进程信号处理程序(armv7-uclibc)中获得适当的回溯?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/1023885.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-23
下一篇 2022-05-23

发表评论

登录后才能评论

评论列表(0条)

保存