所有线程都在核心转储文件中等待,但有人触发了SIG_ABRT

All threads in wait in core dump file, but someone triggered SIG_ABRT

本文关键字:SIG ABRT 等待 线程 核心 转储 文件      更新时间:2023-10-16

多年来,我一直在支持一个用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个线程以最高性能并发运行。要避免这种情况,请执行以下步骤,这些步骤可能会对您有所帮助。

  1. 控制线程的创建。控制并发运行的线程数
  2. 增加应用程序的内存大小。(检查编译器选项以在运行时增加应用程序的内存,或检查O/S以分配足够的内存)
  3. 正确设置每个线程的网格大小和堆栈大小。(需要根据应用程序的线程功能进行计算,这有点复杂。请阅读一些文档)
  4. 正确处理同步块以避免任何死锁
  5. 必要时使用条件锁等

正如您所说的,大多数线程都处于等待状态,这意味着它们正在等待轮到它们的锁释放,也意味着其中一个线程已经获得了锁,并且仍在忙于处理或可能处于死锁状态。