【问题标题】:Other thread position其他螺纹位置
【发布时间】:2016-09-01 11:24:02
【问题描述】:

我的代码出现死锁,我想调试它。 由于某些原因,我无法在此处对其进行重构。这个问题只在我的客户身上重现。

我的想法是每小时轮询一次线程并检查它们是否卡在有问题的代码中。我知道有一个选项可以使用__line____file__ 打印当前代码行。我可以对另一个线程做吗?

以我为例 - 我希望我的线程对其他线程进行采样并打印它们当前的代码行。

编辑 - 我的平台是 RHEL 5.6,代码是 C++。

【问题讨论】:

  • 你的平台是什么?
  • __line____file__ 只是文字。您可以将它们输入一个字符串并将该字符串“发送”到另一个线程。
  • @Hayt OP 不知道死锁发生在哪里。否则 OP 不会提出问题。
  • 死锁检测并不是那么容易,有时它意味着 S.O.帮助。从内部应用程序本身检查死锁,这是不可能的。也许您可以构建一个与您的应用程序交互的外部工具,利用一些 S.O. api。或者,当代码卡住时,可能会将调试程序附加到执行代码上。其实我在考虑看门狗
  • @Hayt 除非我们知道平台与__LINE____FILE__ 无关

标签: c++ c multithreading


【解决方案1】:

它可能有一些怪癖,但这里有一种方法

#include <iostream>
#include <string>

#define TRACK t.line = __LINE__; t.file=__FILE__;
struct Track
{
    int line;    
    std::string file;
};

int main()
{
  Track t;
  TRACK int i = 0;
  std::cout << t.file;
}

您可以在每个语句之前添加“TRACK”,并从另一个线程访问 Track 对象以打印出跟踪线程的位置。

【讨论】:

  • 这如何帮助识别多线程服务器应用程序中的死锁?即使您成功地将 TRACK 宏放入源代码的每一行,并且在每隔一行添加一个调试输出,您也会彻底改变时间(除了std::cout &lt;&lt; 不是线程安全的,我相信)所以甚至可能根本不会发生死锁。
  • 他没有要求识别死锁。他正在寻求一种方法来确定另一个线程的位置。
  • 不要太正式。他不需要那个。他需要找到一个僵局
  • 是的,我知道。但是如果没有发布代码,我们就无能为力了。所以他想用一种“可视化”线程流的方式自己找到它(比如记录输出,这可能是一种更聪明的方式)。尽管您是对的,但找到死锁将是理想的解决方案。
  • 如果没有了解平台,我们无法帮助他。在这种情况下,发布代码无济于事。你认为他的应用有 20 行吗?
【解决方案2】:

当我怀疑这一点时,我通常使用pstack。它不需要更改代码并显示应用程序中所有线程的状态。我一个接一个地运行pstack 几次并比较结果。

【讨论】:

  • 谢谢!但这个问题并没有在我们的实验室重现。仅限于我们的一些客户。我无法在客户的环境中运行 pstack。他永远不会允许我在他的服务器上调试东西。
  • @user296589 您可以要求他们运行应用程序,然后只给您日志文件。 pstack 不会干扰应用程序代码,也不会暴露任何客户数据。此外,当完成相同的处理但无法访问真实数据时,一些客户拥有我们所谓的“生产实验室”。如果存在,您可以在他们的生产实验室中尝试这种方法。
  • @user296589 因为客户可以运行您以二进制形式发布的应用程序(我对吗?),他应该对定期运行甚至开源的统计收集模块没有任何意见。你怎么看?
  • 奇怪的是,我尝试在实验室机器中使用 pstack。它只转储了 11 个线程,而有数百个线程。不在他们身上的是被卡住的线程。也许他们的深度线程数有限制(如子线程等)。
  • 可能是pstack 问题。您可以使用 gdb 模拟 pstackgdb -batch -p &lt;PID&gt; -x &lt;FILE&gt; 其中 包含以下命令:thread apply all bt
【解决方案3】:

我建议遵循这样的策略:

  • 确定究竟是什么线程产生了死锁
  • 确定这些线程的最后工作代码
  • 找出它们之间发生死锁的原因。

然后,这取决于您使用的线程库和平台。让我们假设 pthreads + linux pc。

  • 在这里您可以打印 pthread_self() 和时间戳,然后分析卡住的那个。这将改变时间,这样就不会发生死锁。在这种情况下,您应该考虑如何优化它以不影响再现性(即集成输出或在内部收集它,然后通过调试器或其他方式读取)
  • 确定嫌疑人后,转到他们的实现并搜索他们可以卡住的地方以确定死锁的对象。
  • 当您了解线程和对象后,您应该分析它们是如何动态使用对象的。然后将这种动态行为映射到对象的属性,您就会知道为什么会发生这种情况。

【讨论】:

  • 感谢您的想法。我已经按照你说的做了。它们中的大多数已经存在于我们的代码中。我有问题的功能以及哪些线程被卡住了。但是里面有很多种互斥锁以及我不知道的数千行代码。我只需要一种干净的方式来打印特定时间戳中的线程位置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-28
  • 2011-04-01
  • 2011-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多