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

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

问题描述:

我支持用C++编写多年的应用程序,最近它已经开始崩溃,提供我们不知道如何处理的核心转储。 它运行在一个设备上的Ubuntu 14.04.5核心转储文件中等待的所有线程,但有人触发SIG_ABRT

当加载在GDB的核心文件,它说: 计划与信号SIGABRT终止,中止

我可以检查230个线程,但他们都在等待( )在完全相同的记忆位置。

有一个ID 1的线程,理论上可以是负责任的,但线程也在等待。

所以我基本上有两个问题。

线程的id索引是如何工作的? GDB ID是最后一个活动线程的线程?或者是一个任意的索引和失败可以在任何其他线程?

当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 ??() 

问候 乔恩

+0

什么是从GDB'backtrace'命令线程1 *输出的完整? –

+0

更新上面.. –

如何线程的ID索引工作? GDB ID是最后一个活动线程的线程?

当程序在GDB下运行时,GDB会在线程发现它时给线程编号,所以线程1总是主线程。

但是,当加载一个core转储时,GDB按照内核保存它们的顺序发现线程。我见过的内核总是先保存导致程序终止的线程,因此通常将core加载到GDB中会立即让您进入崩溃点,而无需切换线程。

当SIGABRT被触发时,所有线程如何等待()?

有一种可能性是您没有正确分析core。尤其是,您需要精确共享库的副本,这些共享库在生产core时使用过,当应用程序在“设备”上运行并且您正在开发计算机上分析core时,情况不太可能如此。见this answer

+0

我现在认识到(事后看来)我可能有点快速推断位置是wait()。这是几周前,但我似乎还记得在另一个核心转储中看到。 但在这种情况下,我们只看到?而且我认为这表明两次由bt判断释放相同的记忆。 但是,所有其他线程都处于完全相同的内存位置。那些线程正在等待使用。但同样,这可能是过于快速的假设... –

+0

感谢您,我分析机器的副本的核心文件,使库应该是相同的方式:) 的答复。不过,我必须通过apt-get为共享库安装调试符号,但这应该是安全的吗? –

+0

只要不触发库升级,安装调试信息是安全的。 –

当触发SIGABRT时,所有线程如何在wait()

wait POSIX的功能,还是从运行时环境的东西吗?你在寻找更高级的回溯?

无论如何,有一个简单的解释为什么会发生这种情况:SIGABRT被发送到进程,而不是以同步方式由线程生成。也许一个同事在观察了僵局之后发出了信号来创建核心库,为未来的分析收集证据?

+0

正如我在下面的答案中提到的,我可能不会100%确定这是wait()了。所有线程都处于确切的内存位置,因为这是一段时间后我不记得我是如何推断出这是等待,而不是分析其他应该等待的线程。 同事可以排除:) –

我刚才看到你的问题。首先我的答案并不是针对你的直接问题,而是针对这种情况的一些解决方案。多线程完全依赖于一台机器的硬件和操作系统。特别是内存和处理器。线程增加意味着更多内存的需求以及处理器的更多时间片。我不认为你的应用程序有超过100个处理器,以便230线程以最高性能同时运行。为了避免这种情况,请执行以下可能对您有帮助的步骤。

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

当你告诉你的大部分线程处于等待状态,这意味着他们正在等待锁释放他们反过来,这意味着该线程的一个已获得锁并仍处于忙碌状态或可能处于死锁状态。