日期:2014-05-16  浏览次数:20830 次

Linux下多线程程序崩溃时如何提取出所有线程的函数调用栈
尝试过三种方法都不凑效
1.libc 中的backtrace函数
2.内联汇编,提取出ebp寄存器的值再回溯出函数调用栈(会有兼容性问题,x86下试过可以,一移植到其他平台就用不了,本人菜鸟,汇编不熟)
3.gcc 内建的两个函数 
Built-in Function: void * __builtin_return_address (unsigned int level)

Built-in Function: void * __builtin_frame_address (unsigned int level) 


这些都是只能提取出当前线程的调用栈信息

望各位大虾赐教,感激不尽 


ps: 是通过signal监听异常信号,要在回调函数中把堆栈信息提取出来

  目前我只能发100分的贴

------解决方案--------------------
突然想到一个,你用gdb调试,用backtrace命令看看。就算不能查看所有线程的栈,但是对程序崩溃的原因调查应该有所帮助吧!
------解决方案--------------------
atexit + backtrace试试。
------解决方案--------------------
探讨
尝试过三种方法都不凑效
1.libc 中的backtrace函数
2.内联汇编,提取出ebp寄存器的值再回溯出函数调用栈(会有兼容性问题,x86下试过可以,一移植到其他平台就用不了,本人菜鸟,汇编不熟)
3.gcc 内建的两个函数
Built-in Function: void * __builtin_return_address (unsigned int level)

Buil……

------解决方案--------------------
我觉得可能是线程处理信号的问题。

linux的线程是轻量级进程,线程有自己的信号处理表,继承于父进程。而内核发送信号的单位是进程级别的,不向所有的线程发信号。

参考一下这个文章:
http://www.ibm.com/developerworks/cn/linux/kernel/l-thread/
------解决方案--------------------
两个问题:

1、你确定捕捉信号的那个位置是在创建线程之前还是之后?

2、你可以考虑把所有线程记录下来,用pthread_kill给所有线程发送一个消息(比如USR1)。在USR1中独立用backtrace打印调用栈。
------解决方案--------------------
gdb下用thread apply all bt这个命令不行么?
------解决方案--------------------
看下下面的页面,或许有帮助
http://www.2cto.com/kf/201107/97270.html
------解决方案--------------------
A backtrace is the series of currently active function calls for the program.
-----------------------------------------

以上是man手册里的一句话,我的理解是:

1)如果用backtrace函数记录堆栈信息,应当在每个需要记录堆栈信息的函数体内运行这个函数(这时堆栈正常);

2)当异常发生时,比如楼主说的Test2()函数内除零,只有在Test2函数上下文环境没有被破坏时,
backtrace才能正常运行,如果在信号处理函数里运行backtrace时,之前的上下文可能已经不存在了;
因为信号处理函数注册后,在内核发出异常信号后被程序捕捉执行,这时信号处理函数内的backtrace读取的是这个时刻的上下文环境;

3)信号处理函数是进程中所有线程共享的,任何一个线程改变了信号处理函数,都影响其它线程;
与硬件故障或计时器超时相关信号被发送到引起该事件的线程中去;
其它信号则被发送到任意一个线程,在Linux中,就是当前进程的第一个线程;

我是菜鸟,一点拙见,欢迎批评指正;