所有线程都在核心转储文件中等待,但有人触发了SIG_ABRT
All threads in wait in core dump file, but someone triggered SIG_ABRT
多年来,我一直在支持一个用C++编写的应用程序,但最近它开始崩溃,提供了我们不知道如何处理的核心转储。它在Ubuntu 14.04.5 上的设备上运行
当在GDB中加载核心文件时,它会说:程序终止,信号为SIGABRT,中止
我可以检查230个线程,但它们都在wait()中,处于完全相同的内存位置。
有一个ID为1的线程理论上可能是负责的,但该线程也在等待中。
所以我基本上有两个问题。
线程的id索引是如何工作的?GDB ID为1的线程是最后一个活动线程吗?或者这是一个任意的索引,而失败可能发生在任何其他线程中?
当SIGABRT被触发时,如何所有线程都处于wait()中?当操作系统决定停止进程时,指令指针不应该在失败的命令上吗?还是某种死锁保护?
非常感谢您的帮助。
线程1的回溯:
#0 0xf771dcd9 in ?? ()
#1 0xf74ad4ca in _int_free (av=0x38663364, p=<optimized out>,have_lock=-186161432) at malloc.c:3989
#2 0xf76b41ab in std::string::_Rep::_M_destroy(std::allocator<char> const&) () from /usr/lib32/libstdc++.so.6
#3 0xf764f82f in operator delete(void*) () from /usr/lib32/libstdc++.so.6
#4 0xf764f82f in operator delete(void*) () from /usr/lib32/libstdc++.so.6
#5 0x5685e8b4 in SlimStringMapper::~SlimStringMapper() ()
#6 0x567d6bc3 in destroy ()
#7 0x566a40b4 in HttpProxy::getLogonCredentials(HttpClient*, HttpServerTransaction*, std::string const&, std::string const&, std::string&, std::string&) ()
#8 0x566a5d04 in HttpProxy::add_authorization_header(HttpClient*, HttpServerTransaction*, Hosts::Host*) ()
#9 0x566af97c in HttpProxy::onClientRequest(HttpClient*, HttpServerTransaction*) ()
#10 0x566d597e in callOnClientRequest(HttpClient*, HttpServerTransaction*, FastHttpRequest*) ()
#11 0x566d169f in GateKeeper::onClientRequest(HttpClient*, HttpServerTransaction*) ()
#12 0x566a2291 in HttpClientThread::run() ()
#13 0x5682e37c in wa_run_thread ()
#14 0xf76f6f72 in start_thread (arg=0xec65ab40) at pthread_create.c:312
#15 0xf75282ae in query_module () at ../sysdeps/unix/syscall-template.S:82
#16 0xec65ab40 in ?? ()
另一个应该等待的线程:
#0 0xf771dcd9 in ?? ()
#1 0x5682e37c in wa_run_thread ()
#2 0xf76f6f72 in start_thread (arg=0xf33bdb40) at pthread_create.c:312
#3 0xf75282ae in query_module () at ../sysdeps/unix/syscall-template.S:82
#4 0xf33bdb40 in ?? ()
致以最良好的问候Jon
触发
SIGABRT
时,如何使所有线程都处于wait()
中?
wait
是POSIX函数,还是运行时环境中的函数?你在看更高级别的回溯吗?
无论如何,有一个简单的解释可以解释为什么会发生这种情况:SIGABRT
被发送到进程,而不是由线程以同步方式生成的。也许是一位同事在观察到死锁后发出了创建coredump的信号,以收集证据进行未来的分析?
线程的id索引是如何工作的?GDB ID为1的线程是最后一个活动线程吗?
当程序在GDB下运行时,GDB会在发现线程时对线程进行编号,因此线程1始终是主线程。
但是在加载core
转储时,GDB会按照内核保存线程的顺序来发现线程。我看到的内核总是先保存导致程序终止的线程,所以通常将core
加载到GDB中会立即导致崩溃,而无需切换线程。
SIGABRT被触发时,所有线程如何都处于wait()中?
一种可能是您没有正确分析core
。特别是,您需要生成core
时使用的共享库的精确副本,而当应用程序在"设备"上运行并且您正在开发机器上分析core
时,情况不太可能如此。看看这个答案。
我刚刚看到你的问题。首先,我的回答不是针对你的直接问题,而是处理这种情况的一些解决方案。多线程完全取决于机器的硬件和操作系统。尤其是内存和处理器。线程的增加意味着处理器需要更多的内存和更多的时间片。我不认为您的应用程序有超过100个处理器来促进230个线程以最高性能并发运行。要避免这种情况,请执行以下步骤,这些步骤可能会对您有所帮助。
- 控制线程的创建。控制并发运行的线程数
- 增加应用程序的内存大小。(检查编译器选项以在运行时增加应用程序的内存,或检查O/S以分配足够的内存)
- 正确设置每个线程的网格大小和堆栈大小。(需要根据应用程序的线程功能进行计算,这有点复杂。请阅读一些文档)
- 正确处理同步块以避免任何死锁
- 必要时使用条件锁等
正如您所说的,大多数线程都处于等待状态,这意味着它们正在等待轮到它们的锁释放,也意味着其中一个线程已经获得了锁,并且仍在忙于处理或可能处于死锁状态。