C 我可以在多线程(pthreads)应用程序中捕获SIGSEGV和其他信号,并打印导致它的线程的回溯跟踪,还是打印所有线程的回溯跟踪?

C 我可以在多线程(pthreads)应用程序中捕获SIGSEGV和其他信号,并打印导致它的线程的回溯跟踪,还是打印所有线程的回溯跟踪?,c,linux,multithreading,C,Linux,Multithreading,我看到了,但是里面没有很多实用的信息 我想要的是能够使用Linux(CentOS,2.6内核)上运行的POSIX线程在C多线程应用程序中捕获SIGSEGV,并打印导致它的线程的堆栈跟踪。当然,不知道是哪个线程引起的,捕获信号的主线程枚举所有线程并打印所有线程的堆栈跟踪对我来说已经足够了(tm) 有人在那里指出,也许可以用于此,但它的文档相当缺乏,我找不到一个很好的例子来说明如何将其用于此目的。另外,我想知道它是否有任何显著的性能开销或其他影响,它是否经过战斗测试并用于生产代码,或者它是否主要用于

我看到了,但是里面没有很多实用的信息

我想要的是能够使用Linux(CentOS,2.6内核)上运行的POSIX线程在C多线程应用程序中捕获SIGSEGV,并打印导致它的线程的堆栈跟踪。当然,不知道是哪个线程引起的,捕获信号的主线程枚举所有线程并打印所有线程的堆栈跟踪对我来说已经足够了(tm)

有人在那里指出,也许可以用于此,但它的文档相当缺乏,我找不到一个很好的例子来说明如何将其用于此目的。另外,我想知道它是否有任何显著的性能开销或其他影响,它是否经过战斗测试并用于生产代码,或者它是否主要用于调试和开发,而不是生产系统


是否有人使用libunwind或其他相当简单的方法(如不在汇编中编写)来执行此操作的示例代码?

获取导致异常的线程的回溯很容易,或多或少:

将-rdynamic标志传递给链接器

然后,在coderegister信号处理程序中,从信号处理程序参数中提取故障的EIP,然后使用它和backtrace()函数获取地址数组

找到一些方法将数组中的数据传递到应用程序外部(例如,通过管道传递到不同的进程),然后可以使用backtrace_symbols()将backtrace转换为符号名称

确保不要在信号处理程序中使用任何线程异步非安全函数,不要使用任何锁、分配内存或调用任何这样做的函数

以下是我就这一主题所作的演示的幻灯片:

视频也可以在谈话的某个地方找到,但我现在找不到


扩展此功能以获得多个线程的回溯跟踪是可能的,但相当棘手-您需要保留各种线程的标签,并在崩溃时向它们发送信号

我以前看过这些幻灯片,它们很棒,找到视频后请告诉我。@gby:谢谢您提供的信息,但我不是100%支持您。为什么需要
-rdynamic
?这些幻灯片的代码在哪里?找不到。它能在
x86_64
arch上工作吗?如何将EIP与
backtrace()
一起使用?为什么它需要在流程之外完成?只是因为我无法在sighandler中获得符号?如果我们有其他特定于拱门的代码,在sighandler中遍历ELF符号表,我可以使用它,对吗?@e.dan。backtrace_symbols()使用动态链接器符号将地址转换为符号名称。如果没有-rdynamic,链接器将只嵌入外部库的符号。使用它,您将获得所有非静态符号。密码在里面。它在x86_64上运行良好。关于EIP,您必须阅读幻灯片:-)。@e.dan您需要在进程之外执行此操作,因为刚刚执行分段错误的进程的信号处理程序的位置非常有限-您不能调用任何带锁或分配内存的函数。例如,这意味着没有printf和backtrace_符号。如果不需要锁或任何内存分配,则可以在信号处理程序中使用自定义代码