Using DeadlockDetection

[Previous] [Next]

The first step in using DeadlockDetection is to put DEADLOCKDETECTION.DLL, its initialization file, and the appropriate DeadDetExt DLL in the same place. The initialization file is a simple INI file that, at a minimum, must specify the name of the DeadDetExt file to load. The following sample is a DEADLOCKDETECTION.INI file that loads the supplied TEXTFILEDDEXT.DLL:

[Initialization] ; The only mandatory value, the name of the DeadDetExt ; file that will handle the output ExtDll = "TextFileDDExt.dll" ; If StartInDllMain is 1, DeadlockDetection will ; initialize in its DllMain so that logging can start ; at the earliest possible time. StartInDllMain = 0 ; If StartInDllMain is 1, InitialOpts specifies the ; initial options for DeadlockDetection. This value is a ; combination of the DDOPT_* flags. ; InitialOpts = 0

As you can see from some of the INI settings, DeadlockDetection can initialize just by having LoadLibrary called on it. A good proactive debugging idea would be to create a backdoor in your application initialization that calls LoadLibrary on the specified DLL name if your application sees a special registry key or an environment variable. This alternate approach to initializing your application would mean that you wouldn't need conditional compilation and you'd have a means of getting DLLs into your address space cleanly. Of course, all this assumes that the DLLs you're loading in this way are smart enough to initialize themselves completely in their DllMains and don't require you to call any other exported functions in the DLL.

Having your code set the DeadlockDetection initialization options, rather than using an INI file, means that you'll need to include DEADLOCKDETECTION.H in your application and have your application link against DEADLOCKDETECTION.LIB. If you want to initialize DeadlockDetection yourself, all you need to do is call OpenDeadlockDetection when appropriate. OpenDeadlockDetection takes a single parameter, the initial reporting options. Table 12-2 lists all the DDOPT_* flags. You'll want to call OpenDeadlockDetection before your application starts creating threads so that you can record all the key information about your synchronization objects.

At any point, you can change the reporting options by calling SetDeadlockDetectionOptions. This function takes the same OR'd set of flags as the OpenDeadlockDetection function. To see what the current options are, call GetDeadlockDetectionOptions. You can change the current options as many times as you like during your program's execution. If you want to suspend and resume logging, call the SuspendDeadlockDetection and ResumeDeadlockDetection functions.

Along with the DeadlockDetection source code on the companion CD, I've included a DeadDetExt DLL that I wrote, TEXTFILEDDEXT.DLL. This relatively simple extension writes all the information to a text file. When you run DeadlockDetection with TEXTFILEDDEXT.DLL, the extension creates a text file in the same directory as the executable program. The text file will use the name of the executable with a DD extension. For example, if you run SIMPTEST.EXE, the resulting file will be SIMPTEST.DD. Listing 12-1 shows some sample output from TEXTFILEDDEXT.DLL.

Table 12-2 DeadlockDetection Reporting Options

FlagLimits Logging to
DDOPT_THREADSThread-related functions
DDOPT_CRITSECCritical-section functions
DDOPT_MUTEXMutex functions
DDOPT_SEMAPHORESemaphore functions
DDOPT_EVENTEvent functions
DDOPT_ALLAll hooked functions

Listing 12-1 DeadlockDetection output using TESTFILEDDEXT.DLL

 TID        Ret Addr     C/R Ret Value  Function & Params 0x000000F7 [0x004011AC] (R) 0x00000000 InitializeCriticalSection 0x00403110 0x000000F7 [0x004011C6] (R) 0x00000290 CreateEventA 0x00000000, 1, 0,                                             0x004030F0 [The event name] 0x000000F7 [0x004011E9] (R) 0x00000294 CreateThread 0x00000000, 0x00000000,                                             0x00401000, 0x00000000,                                             0x00000000, 0x0012FF68 0x000000F7 [0x0040120C] (R) 0x00000298 CreateThread 0x00000000, 0x00000000,                                             0x004010BC, 0x00000000,                                             0x00000000, 0x0012FF68 0x000000F7 [0x00401223] (C)            EnterCriticalSection 0x00403110 0x000000F7 [0x00401223] (R) 0x00000000 EnterCriticalSection 0x00403110 0x000000F7 [0x00401238] (C)            WaitForSingleObject 0x00000290,                                             INFINITE 0x000000FF [0x1020B973] (C)            EnterCriticalSection 0x1025CE90 0x000000FF [0x1020B973] (R) 0x00000000 EnterCriticalSection 0x1025CE90 0x0000010C [0x004010F3] (R) 0x000002A4 OpenEventA 0x001F0003, 0, 0x004030BC                                             [The event name]

Notice that the function and parameter information is wrapped in Listing 12-1 to display on the page. The output shows the information in the following order:

  1. The ID of the executing thread.
  2. The return address to indicate which of your functions called the synchronization function. Using the CrashFinder utility from Chapter 8, you can look up the return addresses and discover how you got into the deadlock situations.
  3. The call or return indicator to help identify actions that occur before and after specific functions.
  4. The return value of the function if your program is reporting function returns.
  5. The synchronization function name.
  6. The parameter list for the synchronization function. Items in brackets are the human-readable data. I concentrated on showing string values, but it would be trivial to add more data, such as individual flags.

When you run your application and it deadlocks, kill the process and view the output file to see the last synchronization item called. TEXTFILEDDEXT.DLL keeps the file up to date by flushing the file buffers each time you call a WaitFor* function, EnterCriticalSection, or TryEnterCriticalSection.

A word of caution: if you turn on full logging of all functions, you can generate some extremely large files in no time. Using the MTGDI Visual C++ sample application, I generated an 11-MB text file in a minute or two by creating a couple of threads.



Debugging Applications
Debugging Applications for MicrosoftВ® .NET and Microsoft WindowsВ® (Pro-Developer)
ISBN: 0735615365
EAN: 2147483647
Year: 2000
Pages: 122
Authors: John Robbins

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net