Question

I am attempting to analyze a memory dump that I received from one of my end users after a hang occurred in my application. It seems to be related to the audio playback portion of my application. I believe that there are two threads involved, the main thread which is about to start playing the sound, and an updater thread which iterates over the sounds in a linked list to update their state continuously. I do not understand what the source for the hang could be, however.

My WinDbg knowledge is limited, but I have managed to figure out that the hang seems to occur inside the SetLoop method of the audio library (in the static sound code specifically). I use DirectSound, and the application is running on Windows 7 32 bit in this case (I am developing on XP myself where I have never had an issue like this). The static sound class locks a critical section before it checks to see if the sound is playing, and if it isn't it sets the loop flag to either true or false. In this case, the main thread is calling SetLoop to set it to false because it wants to play the sound in a non-looped state. I can see that at the time of the hang, the main thread is stuck in a call to EtwEventEnabled in ntdll.dll which is apparently made by the SetLoop method of the static sound class. I wonder if it is stuck in the EnterCriticalSection call, or somewhere a little further down when it calls upon DirectSound's GetStatus method for the secondary buffer? Here's where my knowledge of memory dump analysis falls short, and I would very much appreciate it if someone would take the time to look at the dump.

Here is a link to the dump, with the application specific symbols: https://dl.dropbox.com/u/5121962/hangdump.zip

Thanks very much in advance for any help.

Was it helpful?

Solution 2

Two threads (one is WinMain) are waiting on the same critical section 03cb6ffc which has no owner. Look at StaticSound::Update and StaticSound::SetLoop. Maybe thread currently being terminated is still owning a critical section. Try use Application Verifier with Locks Stop Details - Verifies the correct usage for critical sections.

0:000> !analyze -hang -v
[...] 
BUGCHECK_STR:  HANG
[...]

DERIVED_WAIT_CHAIN:  

Dl Eid Cid     WaitType
-- --- ------- --------------------------
   0   768.d1c Critical Section       (Self) 

WAIT_CHAIN_COMMAND:  ~0s;k;;

BLOCKING_THREAD:  00000d1c

DEFAULT_BUCKET_ID:  APPLICATION_HANG_SELF_Unowned_CriticalSection

PRIMARY_PROBLEM_CLASS:  APPLICATION_HANG_SELF_Unowned_CriticalSection

LAST_CONTROL_TRANSFER:  from 77d56a24 to 77d57094
[...]
0:000> !locks
CritSec +13af7d0 at 013af7d0
WaiterWoken        No
LockCount          0
RecursionCount     1
OwningThread       10a8
EntryCount         0
ContentionCount    2b7
*** Locked

CritSec +3cb6ffc at 03cb6ffc
WaiterWoken        No
LockCount          2
RecursionCount     0
OwningThread       0
EntryCount         0
ContentionCount    d
*** Locked

0:000> ~*
.  0  Id: 768.d1c Suspend: 0 Teb: 7ffde000 Unfrozen
      Start: pontefract_timer!WinMainCRTStartup (01299030) 
      Priority: 0  Priority class: 32  Affinity: f
   [...]
   4  Id: 768.10a8 Suspend: 0 Teb: 7ffdb000 Unfrozen
      Start: pontefract_timer!_threadstartex (012ae09f) 
      Priority: 2  Priority class: 32  Affinity: f
    [...]
0:004> kb
ChildEBP RetAddr  Args to Child              
021af9b4 77d56a24 77d42278 000002f0 00000000 ntdll!KiFastSystemCallRet
021af9b8 77d42278 000002f0 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc
021afa1c 77d4215c 00000000 00000000 00000000 ntdll!RtlpWaitOnCriticalSection+0x13e
021afa44 012882c2 03cb6ffc 013af7cc 00326ee8 ntdll!RtlEnterCriticalSection+0x150
021afa60 0128a1ed 021afa8c 021afa80 013af810 pontefract_timer!StaticSound::Update+0x12
021afa84 012ae079 013af700 73a14e26 00000000 pontefract_timer!UpdaterTick+0x7d
021afabc 012ae103 00000000 021afad4 7750ed6c pontefract_timer!_callthreadstartex+0x1b 
021afac8 7750ed6c 013af810 021afb14 77d7377b pontefract_timer!_threadstartex+0x64 
021afad4 77d7377b 013af810 6b63b5bd 00000000 kernel32!BaseThreadInitThunk+0xe
021afb14 77d7374e 012ae09f 013af810 00000000 ntdll!__RtlUserThreadStart+0x70
021afb2c 00000000 012ae09f 013af810 00000000 ntdll!_RtlUserThreadStart+0x1b
0:000> kb
ChildEBP RetAddr  Args to Child              
0020c39c 77d56a24 77d42278 000002f0 00000000 ntdll!KiFastSystemCallRet
0020c3a0 77d42278 000002f0 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc
0020c404 77d4215c 00000000 00000000 774f8e38 ntdll!RtlpWaitOnCriticalSection+0x13e
0020c42c 012881af 03cb6ffc 00000000 03cb6ff8 ntdll!RtlEnterCriticalSection+0x150
0020c440 0128682c 00000000 00000000 00000000 pontefract_timer!StaticSound::SetLoop+0xf
0020c460 012616ac 00000000 00000000 01765bac pontefract_timer!DeviceManager::SetLoop+0x6c
0020c474 0121a2ce 01a46ddc 00000000 0178ea9c pontefract_timer!BgtSound::play+0x6c 
0020c61c 01219d02 0178ea9c 01765bf4 01a46ddc pontefract_timer!CallSystemFunctionNative+0x42e
0020c64c 0121d450 00000000 00000000 0178ea9c pontefract_timer!CallSystemFunction+0xd2 
0020c6d4 0121c276 01a46dfc 77b6ea11 00000000 pontefract_timer!asCContext::ExecuteNext+0x930
0020c708 0127a293 719b431a 0020f780 00000000 pontefract_timer!asCContext::Execute+0x1d6
0020f780 0127a1d5 719b4c6a 77b1f2a9 0010000c pontefract_timer!execute+0x83
0020f8f0 0127acff 77b1f2a9 77b18d02 0020f958 pontefract_timer!RunApplication+0x805 
0020f908 0127b085 0020f908 0127b339 00000000 pontefract_timer!run_script+0x9f
0020f910 0127b339 00000000 00000000 7ffdf000 pontefract_timer!main_game+0x35
0020f958 01298fdd 01210000 00000000 00361f32 pontefract_timer!WinMain+0x2a9
0020f9e8 7750ed6c 7ffdf000 0020fa34 77d7377b pontefract_timer!__tmainCRTStartup+0x11a 
0020f9f4 77d7377b 7ffdf000 6959b49d 00000000 kernel32!BaseThreadInitThunk+0xe
0020fa34 77d7374e 01299030 7ffdf000 00000000 ntdll!__RtlUserThreadStart+0x70
0020fa4c 00000000 01299030 7ffdf000 00000000 ntdll!_RtlUserThreadStart+0x1b

OTHER TIPS

You could try analysing the dump with Microsoft's Debug Diagnostics Tool - it seems to confirm what you suspect, but without your knowledge of the code or the Release build PDB's for your exe, I can't get more info from the call stack.

From the report (you can run the full analysis yourself using the tool) there are two threads involved - the summary is as follows:

Summary of problem

The call stacks of threads 0 and 4 are as follows:

Thread 0

.. and ...

Thread 4

These might give you some more info to get you moving again....

Hope that helps,

Roger

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top