如何在Delphi应用程序中调试挂主线程

时间:2010-01-14 11:13:27

标签: delphi debugging thread-safety hang

我在Delphi 2007中编写了应用程序,有时会挂起(甚至不是每周都有应用程序运行24/7)。看起来主线程卡住了。有哪些方法可以找出导致此问题的原因?

应用程序是用Delphi 2007编写的,它使用RemObjects,DBExpress和Firebird,使用COM进行OPC通信。

2 个答案:

答案 0 :(得分:11)

使用MadExcept,您可以指定定期检查主线程以仍处理消息(使用变量超时,您将设置为高于最长操作所需的值)。如果主线程挂起,则可以获得堆栈跟踪。

请参阅Main thread freeze checking...

我已经成功使用了它,但只有当挂起在驱动程序中时才会失败(这可能是预期的)。在开始怀疑驱动程序(对于A / D转换卡)之后,我在每个API调用之前和之后添加了跟踪消息,并且能够证明驱动程序是罪魁祸首。请注意,立即将消息写入文件并刷新缓冲区以获取可靠的日志数据非常重要。

我还成功地使用WinDbg附加到没有安装Delphi的系统上挂起的可执行文件。事实证明,这并不总是以相同的顺序获取关键部分。 WinDbg通过检查线程堆栈和关键部分的状态来帮助分析这种情况。

答案 1 :(得分:4)

我为此使用了一个“看门狗”线程,它检查主机是否响应,并制作一个minidump(您可以使用WinDbg加载此转储,使用map2dbg.exe将Delphi .map转换为.dbg)。

FMainformHandle := Application.MainForm.Handle;
Result := SendMessageTimeOut( FMainformHandle, WM_NULL, 0, 0,
      SMTO_NORMAL or SMTO_ABORTIFHUNG,
      C_TIME_OUT_SECONDS * 1000, //wait 1minute
      iRes) <> 0;
if not Result then
begin
   hFile := CreateFile(PChar(Result), GENERIC_WRITE, FILE_SHARE_WRITE, nil,
         CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
   try
      MiniDumpWriteDump(GetCurrentProcess, GetCurrentProcessId, hFile,
            aDumpType, nil, nil ,nil);
   finally
      FileClose(hfile);
   end;
end;

但你也可以使用

  

jclDebug.pas:
  JclCreateThreadStackTraceFromID(MainthreadId)

为此(不需要WinDbg等,只有JCL + Delphi .map)

第三个选项是使用我的新sampling profiler,它有一个“进程堆栈查看器”,所以你可以看到正在运行的进程的任何线程的堆栈(之前我使用过SysInternals Process Explorer,但它需要.dbg文件)。它使用.map,TD32,JDBG等(任何Delphi调试信息)进行堆栈跟踪 您可以在应用挂起时使用此功能来调查堆栈。

Windows API(适用于MiniDumpWriteDump):
http://sourceforge.net/projects/jedi-apilib/files/JEDI%20Windows%20API/
WinDbg的:
http://www.microsoft.com/whdc/devtools/debugging/installx86.Mspx
Map2Dbg:
http://code.google.com/p/map2dbg/
JEDI JCL:
http://jcl.delphi-jedi.org/
AsmProfiler,采样模式:(仍在开发中!)
http://asmprofiler.googlecode.com/files/AsmSamplingProfiler0.4.zip