views:

638

answers:

4

Hi,

I've written application in Delphi 2007, which some times hangs (not even every week, application is running 24/7). It looks like main thread gets stuck. What are the options to pinpoint the cause for this problem?

Application is written in Delphi 2007, it uses RemObjects, DBExpress with Firebird, OPC communication using COM.

+10  A: 

Using MadExcept you can specify that the main thread is periodically checked to still process messages (with a variable timeout, which you would set to a value higher than your longest actions would take). If the main thread hangs you can thus obtain a stack trace.

See Main thread freeze checking...

I have used this with some success, it only failed when the hang was in a driver (which is probably to be expected). After beginning to suspect the driver (for an A/D conversion card) I added trace messages before and after each API call and was able to prove the driver being the culprit. Note that it will be important to immediately write messages to a file and flush the buffers in order to get reliable log data.

I have also successfully used WinDbg to attach to a hanging executable on a system without installed Delphi. This turned out to be a deadlock from not always acquiring critical sections in the same order. WinDbg helps analyse such situations by examining the thread stacks and the state of critical sections.

mghie
I use a circular buffer of Record types to store a continuous "sequence of events" log on disk, which will help me establish the state of the software immediately before the lockup.The kinds of problems you are likely to be dealing with are:1. Deadlock: Not only because code is written in ways that will clasically deadlock. You could even fail to put try..finally block around a critical section of code, and then not exit the critical section.2. An API call freeze-up, such as the driver issue above.
Warren P
Warren P: How do you do event logging? What kind of events you log?
Harriv
+3  A: 

I used a "watchdog" thread for this, which checks if the mainform is responding, and make a minidump (you can load this dump with WinDbg, use map2dbg.exe to convert a Delphi .map to a .dbg).

FMainformHandle := Application.MainForm.Handle;
Result := SendMessageTimeOut( FMainformHandle, WM_NULL, 0, 0,
  SMTO_NORMAL or SMTO_ABORTIFHUNG,
  //wait 1minute
  C_TIME_OUT_SECONDS * 1000, 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;

But you can also use

jclDebug.pas:
JclCreateThreadStackTraceFromID(MainthreadId)

for this (no need for WinDbg etc, only the JCL + Delphi .map)

3rd option is to use my new sampling profiler, which has a "process stack viewer", so you can watch the stack of any thread of a running process (I used SysInternals Process Explorer for this before, but it needs .dbg files). It uses .map, TD32, JDBG etc (any Delphi debug info) for stack tracing.
You can use this when you app hangs, to investigate the stack.

Windows API (for 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, samling mode: (still under development!)
http://asmprofiler.googlecode.com/files/AsmSamplingProfiler0.4.zip

André
Is possible to attach sampling profiler to hung application or should it be running constantly?
Harriv
you can "view" a running process, as long as exists, so a hung app too :-).It is a small addition to the profiler, because I was tired of converting map2dbg everytime with Process Explorer...
André
+1  A: 

I recommend this article: "How to debug application’s hang?" ;)

Alexander
A: 

This Delphi 2006 application has run successfully for several years. I have narrowed it hanging up to some point before it gets to the "initialize" in the DPR file so its hanging up before any written code gets executed. I press the "Run" icon and it never displays anything else, just stops running. Not much info to give, any ideas?

George Bean
You may want to create a new question for your problem to get more attention.
Harriv