如何处理在Delphi中挂起的第三方函数或线程?

时间:2012-08-15 16:26:33

标签: delphi delphi-7

我在Delphi 7服务应用程序,Indy,Synapse,Zeolibs等中使用了很多组件。

我的应用程序通常是稳定的,我使用Eurekalog 6来捕获异常,但在极少数情况下,某些线程会挂起,因为它调用的第三方函数已挂起,例如当试图发送电子邮件时,Indy陷入困境。

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

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

2 个答案:

答案 0 :(得分:10)

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

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

现在,杀死进程(而不是特定的线程)并依赖监视程序服务来重启进程是安全的。但这是一个非常可怕的解决方案。

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

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

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

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

答案 1 :(得分:2)

你的问题太模糊了。如果你不知道你所使用的各种组件中哪一个是你想要责备的,那么你就没有希望修复它。最可能的是你做错了什么,或者你不明白这些组件是如何工作的。我非常怀疑它纯粹是组件本身的一个错误,但是嘿,无论哪种方式,你都可以找到有问题的东西,以及你的工作来解决它。

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

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

然而,在你弄清楚问题出在哪里之前,我怀疑你是否能解决它。所以,为此,马库斯是对的,你应该研究疯狂的除外。没有它我就活不下去。

其次,你应该真正为你的程序添加跟踪逻辑,这样你才能知道它在哪里以及它在出现问题之前所做的工作。如果您确实需要帮助,可以尝试使用Raize的CodeSite。我个人认为OutputDebugString与免费的Microsoft DebugView实用程序(以前来自SysInternals)工具相结合,足以在客户端计算机上调试此类问题。

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

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