2

我在我的 Delphi 7 Service 应用程序、Indy、Synapse、Zeolibs 等中使用了很多组件。

我的应用程序总体上是稳定的,我使用 Eurekalog 6 来捕获异常,但在极少数情况下,一些线程会挂起,因为它调用的第 3 方函数挂起,例如 Indy 在尝试发送电子邮件时卡住了。

在很多情况下,挂起的应用程序是我客户的地方,我无法访问他们的计算机,因此我无法进行实时调试。我的应用程序需要高可用性,因此即使它每年挂起一次,我的用户也无法接受。

我现在正在寻找最好的方法来处理这种调试不可行但我仍然需要应用程序自行恢复的情况。如果线程调用的函数挂起,线程是否可以终止?或者,我也可以在发生这种情况时重新启动整个服务。看门狗怎么样?实现它的最佳方法是什么?谢谢。

4

2 回答 2

10

我认为你是相当失败主义者。查找并修复错误。这可能很棘手,但这是正确的解决方案。

杀死你不理解行为的线程永远不是解决方案。如果你开始杀死线程,你可能会让事情变得更糟。这可能导致其他运行时错误、死锁等。一旦你开始杀死线程,你就失去了控制。

现在,杀死进程(而不是特定线程)并依靠看门狗服务重新启动进程是安全的。但这是一个非常可怕的解决方案。

您当然应该使用 madExcept、EurekaLog 等工具来调试意外异常。我看到你已经在使用 EurekaLog - 这很好。

死锁(听起来你有死锁)可能更难追上。调试死锁的一种好方法是让您的客户端生成故障转储(例如,来自 Process Explorer)。然后在 WinDbg 中使用 map2dbg 对其进行调试以生成符号堆栈跟踪。这将告诉您哪些线程正在阻塞并揭示死锁。然后修复错误。

有关此死锁调试技术的更多详细信息,请参见此处:http ://capnbry.net/blog/?p=18

我不熟悉 EurekaLog,因为我使用了 madExcept,但我希望 EurekaLog 具有允许为挂起进程生成线程堆栈跟踪的工具。如果是这样,那么这很可能是您的最佳方法。

于 2012-08-15T18:40:47.743 回答
2

你的问题太模糊了。如果您不知道要归咎于您正在使用的各种组件中的哪一个,那么您修复它的希望为零。最有可能的是您做错了什么,或者您不了解这些组件的工作原理。我非常怀疑这纯粹是组件本身的错误,但是,嘿,无论哪种方式,都取决于您找出问题所在,并解决问题。

您创建的死锁或正在发生的深层进程损坏问题可能会阻止 MadExcept 向您提供任何信息,但值得一试。

要找出哪个是冻结的,如果有的话,那么 madexcept 评论是最好的建议。它将超时(在可配置的秒数之后)并为您引发人为异常,从而中断您挂起的过程。这适用于用户代码,以及线程在 Win32 或内核函数中被阻塞的地方。例如,您可能已将 Indy 设置为无限超时,因为这是 Indy 10 中这些天的默认设置,并且您遇到的是与超时相关的冻结,您希望完成但从未完成的网络活动将完成,导致您的程序“挂起”。这里的解决方法是改变你的超时。

但是,在您弄清楚问题出在哪里之前,我怀疑您是否能够解决它。所以,为此,Marcus 是对的,你应该调查 madExcept。没有它我活不下去。

其次,你真的应该在你的程序中添加跟踪逻辑,这样你就知道它的去向以及在它出现问题之前它在做什么。如果你真的需要帮助,你可以试试 Raize 的 CodeSite。就我个人而言,我发现OutputDebugString结合免费的 MicrosoftDebugView实用程序(以前来自 SysInternals)工具足以在客户端计算机上调试此类问题。

任何具有后台线程但没有跟踪日志记录的程序都是设计不佳的程序。哎呀,任何可能失败或有问题的重要单线程应用程序都需要跟踪日志记录。

即使 MadExcept 或其他异常工具没有帮助,日志记录总是会有所帮助。尽管 CodeSite 也很受欢迎,但 Trace-Logging 通常是一个自己动手的解决方案。

于 2012-08-15T19:02:23.857 回答