PrefaceAfter releasing the newest version of our software to a customer, we got complaints about a hanging Windows Service. There were no errors or stack traces of those moments, so I wanted to take a look at that service when it hangs (mostly see the stacks of a threads) with my (simple) Process Stack viewer. However, it happened in the early morning and they also could not wait till I was logged in anyway because of the production process. So they directly restart the service when it happens. I already made a simple "all thread dump" (stack traces of all threads) which is executed when a service is stopped (you normally don't stop a service, so when you stop it there is something wrong). But not all services made such a dump, so they were really "hanging".
The next solution was to make a minidump. This can be done by any program and contains all kind of information: dll's, threads, etc. It is a snapshot of the process. However, you need Microsoft compatible debug symbols to view it in WinDbg (part of Microsoft Debugging Tools). You can use map2dbg to convert a Delphi .map file to a Microsoft .dbg file, but this does not always work and more important: .dbg files are not supported and used anymore! Only .pdb files can be used (more about that in another blog).
Reading a minidump
Fortunately, reading a minidump file is good documented, and also the record structures are converted to Delphi in JwaImageHlp.pas (part of the JEDI Windows API libary). So I created a small app to read some contents of a minidump file: system and cpu information, loaded modules, threads, etc. However creating a stack trace is little bit difficult: jclDebug.pas can only create stack traces of the current process, not of an offline process! But I already created some code for this in my sampling profiler, so I copied this code and modified it a bit, et voila: the stack traces of all threads in a mindump! (you need the original exe with the corresponding debug information: .map file, embedded .jdbg file, etc).
I only made a simple "raw" stack tracer (not by stack frames yet), so you get a lot of bogus and false positives because everything on the stack that is a possible code pointer is shown. But at least it works! :-)
How to use
First you need to make a minidump: see the demo project how to do this.
Then you can load this in the Minidump Viewer:
1: Load the dump
2: Show minidump content
Note: the original exe is tried to be loaded from the original location as stored in the minidump. If this file cannot be loaded, it is tried to be loaded from the current directory. The location is shown besides the "Load original exe" button. Use this button if you want it to be loaded from a different location (before clicking the "Show minidump content" button!)
Note 2: make sure you have the right debug symbols! So the original .exe + original .map file, or even better: the original .exe with embedded JDBG.