Hung Window?, No source?, No problem!! Part 1

Hung Window?, No source?, No problem!! Part 1

  • Comments 2

Written by Jeff Dailey

 

Hello, my name is Jeff, I’m a escalation engineer on the Microsoft CPR Platforms team.   This blog entry is a follow on for how to detect a hung window.   This process and training lab is right out of our CPR Training curriculum.  In order to do the lab I have prepared for you, you will need to have downloaded the dumphungwindow and then badwindow.exe from my earlier blog post.  You will also need to install the debugging tools for windows.  

 

Debugging tools:  http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx

Previous blog http://blogs.msdn.com/ntdebugging/archive/2007/05/29/detecting-and-automatically-dumping-hung-gui-based-windows-applications.aspx

 

After you have both of these installed we can get started.  We are going to debug and figure out why the window stops repainting and does not respond.

 

Step 1 start badwindow.exe

Step 2 run dumphungwindow.exe

Step 3 select Hang \ Hang Type 1 from  the BadWindow.exe menu.

 

You should see dump hung window detect your window no processing messages and as a result it will dump the badwindow.exe process

 

************ OUTPUT *************

C:\source\dumphungwindow\release>dumphungwindow.exe
Dumps will be saved in C:\Users\jeffda\AppData\Local\Temp\
scanning for hung windows

**

Hung Window found dumping process (7924) badwindow.exe
Dumping unresponsive process
C:\Users\jeffda\AppData\Local\Temp\HWNDDump_Day6_12_2007_Time9_53_34_Pid7924_badwindow.exe.dmp

Dump complete

Hung Window found dumping process (7924) badwindow.exe
Dumping unresponsive process
C:\Users\jeffda\AppData\Local\Temp\HWNDDump_Day6_12_2007_Time9_53_46_Pid7924_badwindow.exe.dmp

Dump complete

Hung Window found dumping process (7924) badwindow.exe
Dumping unresponsive process
C:\Users\jeffda\AppData\Local\Temp\HWNDDump_Day6_12_2007_Time9_53_56_Pid7924_badwindow.exe.dmp

Dump complete*

************ OUTPUT *************

 

Step 4 create a local symbol directory at C:\websymbols

Step 5 set your symbol path under file \ symbols in windbg to SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols

See http://www.microsoft.com/whdc/devtools/debugging/debugstart.mspx for details.

 

Step 6 start windbg select file\open crash dump and select the first dump file.

Your initial output should look like this.

 

Microsoft (R) Windows Debugger  Version 6.7.0001.0

Copyright (c) Microsoft Corporation. All rights reserved.

 

***** WARNING: Your debugger is probably out-of-date.

*****          Check http://dbg for updates.

 

Loading Dump File [C:\Users\jeffda\AppData\Local\Temp\HWNDDump_Day6_12_2007_Time9_53_34_Pid7924_badwindow.exe.dmp]

User Mini Dump File with Full Memory: Only application data is available

 

Symbol search path is: Symbol search path is: SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols

Executable search path is:

Windows Vista Version 6000 MP (2 procs) Free x86 compatible

Product: WinNt, suite: SingleUserTS

Debug session time: Tue Jun 12 09:53:35.000 2007 (GMT-4)

System Uptime: 11 days 18:41:43.089

Process Uptime: 0 days 0:00:32.000

....................................

Loading unloaded module list

.

eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=004e3750 edi=004d9c60

eip=777fb2b2 esp=0017ee18 ebp=0017ee44 iopl=0         nv up ei pl nz na po nc

cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202

ntdll!NtAlpcSendWaitReceivePort+0x12:

777fb2b2 c22000          ret     20h

 

Step 7 from the debugger prompt (Locate a prompt at the bottom of windbg that has a 0:000> next to it.
Type ~* k

You will most likely see output similar to this.

 

.  0  Id: 1ef4.17a8 Suspend: 0 Teb: 7efdd000 Unfrozen

ChildEBP RetAddr 
0017ee14 76f584c5 ntdll!NtAlpcSendWaitReceivePort+0x12
0017ee44 76f5899d rpcrt4!LRPC_CASSOCIATION::AlpcSendWaitReceivePort+0x2f
0017ee78 76f58514 rpcrt4!LRPC_BASE_CCALL::DoSendReceive+0x48
0017ee90 76f57785 rpcrt4!LRPC_BASE_CCALL::SendReceive+0x2c
0017eea0 76f5766b rpcrt4!I_RpcSendReceive+0x25
0017eeb4 76f5763a rpcrt4!NdrSendReceive+0x31
0017eec0 76ff0146 rpcrt4!NdrpSendReceive+0x9
0017f2c8 756e5ff3 rpcrt4!NdrClientCall2+0x18f
0017f2e0 756e5ef9 dnsapi!R_ResolverQuery+0x19
0017f34c 756e5d34 dnsapi!Query_PrivateExW+0x257
0017f388 756e6025 dnsapi!Query_Shim+0xbb
0017f3b0 74f461b4 dnsapi!DnsQuery_W+0x20
0017f3e0 74f4611c mswsock!SaBlob_Query+0x2d
0017f424 74f459db mswsock!Rnr_DoDnsLookup+0x129
0017f6c0 76d75a72 mswsock!Dns_NSPLookupServiceNext+0x25c
0017f6d8 76d75a52 ws2_32!NSPROVIDER::NSPLookupServiceNext+0x17
0017f6f4 76d75994 ws2_32!NSPROVIDERSTATE::LookupServiceNext+0x1c
0017f720 76d7590a ws2_32!NSQUERY::LookupServiceNext+0xa4
0017f764 76d7b11f ws2_32!WSALookupServiceNextW+0x74
0017f7b4 76d7ab77 ws2_32!WSALookupServiceNextA+0x52

   1  Id: 1ef4.f80 Suspend: 0 Teb: 7efda000 Unfrozen

ChildEBP RetAddr 
0275fef0 76e41220 ntdll!ZwWaitForSingleObject+0x15
0275ff60 76e41188 kernel32!WaitForSingleObjectEx+0xbe
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for FwcWsp.dll -
0275ff74 55620611 kernel32!WaitForSingleObject+0x12
WARNING: Stack unwind information not available. Following frames may be wrong.
0275ff88 5561f10c FwcWsp!RatDumpStack+0x1bd
0275ffa0 76eb19f1 FwcWsp!RatDbgPrint+0x156
0275ffac 7782d109 kernel32!BaseThreadInitThunk+0xe
0275ffec 00000000 ntdll!_RtlUserThreadStart+0x23

 

   2  Id: 1ef4.1d04 Suspend: 0 Teb: 7efd7000 Unfrozen
ChildEBP RetAddr 
028cfe90 76e4edb5 ntdll!ZwWaitForMultipleObjects+0x15
028cff2c 76e430c3 kernel32!WaitForMultipleObjectsEx+0x11d
028cff48 5560c841 kernel32!WaitForMultipleObjects+0x18
WARNING: Stack unwind information not available. Following frames may be wrong.
028cff84 5560c9c0 FwcWsp!WspDisable+0x1b47
028cffa0 76eb19f1 FwcWsp!WspDisable+0x1cc6
028cffac 7782d109 kernel32!BaseThreadInitThunk+0xe
028cffec 00000000 ntdll!_RtlUserThreadStart+0x23

 

Note the [NUMBER] Id: indicates the thread number, to the right of this you have the process id and thread id > PROCESS 1ef4.1d04 < THREAD | THREAD STATE > Suspend: 0 Teb: 7efd7000 Unfrozen

 

Each of these threads represents a call stack.  The most recent call is at the TOP of the stack.  As each call is made the stack grows larger.  In this case thread 0 is not showing us all it’s stack.  We can get more of the stack be specifying the number of frames we would like to see.

 

In this case my current thread is 0 so I will issue a k 123 command asking for as many 123 calls to be displayed.

 

0:000> k 123

ChildEBP RetAddr 

0017ee14 76f584c5 ntdll!NtAlpcSendWaitReceivePort+0x12

0017ee44 76f5899d rpcrt4!LRPC_CASSOCIATION::AlpcSendWaitReceivePort+0x2f

0017ee78 76f58514 rpcrt4!LRPC_BASE_CCALL::DoSendReceive+0x48

0017ee90 76f57785 rpcrt4!LRPC_BASE_CCALL::SendReceive+0x2c

0017eea0 76f5766b rpcrt4!I_RpcSendReceive+0x25

0017eeb4 76f5763a rpcrt4!NdrSendReceive+0x31

0017eec0 76ff0146 rpcrt4!NdrpSendReceive+0x9

0017f2c8 756e5ff3 rpcrt4!NdrClientCall2+0x18f

0017f2e0 756e5ef9 dnsapi!R_ResolverQuery+0x19

0017f34c 756e5d34 dnsapi!Query_PrivateExW+0x257

0017f388 756e6025 dnsapi!Query_Shim+0xbb

0017f3b0 74f461b4 dnsapi!DnsQuery_W+0x20

0017f3e0 74f4611c mswsock!SaBlob_Query+0x2d

0017f424 74f459db mswsock!Rnr_DoDnsLookup+0x129

0017f6c0 76d75a72 mswsock!Dns_NSPLookupServiceNext+0x25c

0017f6d8 76d75a52 ws2_32!NSPROVIDER::NSPLookupServiceNext+0x17

0017f6f4 76d75994 ws2_32!NSPROVIDERSTATE::LookupServiceNext+0x1c

0017f720 76d7590a ws2_32!NSQUERY::LookupServiceNext+0xa4

0017f764 76d7b11f ws2_32!WSALookupServiceNextW+0x74

0017f7b4 76d7ab77 ws2_32!WSALookupServiceNextA+0x52

0017f7e0 76d7dba3 ws2_32!getxyDataEnt+0xbd

0017fa1c 0040147d ws2_32!gethostbyname+0xb4

0017fbc8 004012fc badwindow!hangtype1+0x3d [c:\source\badwindow\badwindow\badwindow.cpp @ 310]

0017fc24 772a87af badwindow!WndProc+0xdc [c:\source\badwindow\badwindow\badwindow.cpp @ 274]

0017fc50 772a8936 user32!InternalCallWinProc+0x23

0017fcc8 772a8a7d user32!UserCallWinProcCheckWow+0x109

0017fd2c 772a8ad0 user32!DispatchMessageWorker+0x380

0017fd3c 004010fb user32!DispatchMessageW+0xf

0017ff0c 00401817 badwindow!wWinMain+0xfb [c:\source\badwindow\badwindow\badwindow.cpp @ 124]

0017ffa0 76eb19f1 badwindow!__tmainCRTStartup+0x150 [f:\sp\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 589]

0017ffac 7782d109 kernel32!BaseThreadInitThunk+0xe

0017ffec 00000000 ntdll!_RtlUserThreadStart+0x23

 

As you can see our current thread is the WinMain thread.   Note this from the call badwindow!wWinMain,  this winmain is processing messages, you can see it calling DispatchMessageW this goes back into User32, and user32 has to rout this message for the proper WinProc that is registered for the associated Window.  

 

Looking further up the stack you see our winproc being called badwindow!WndProc.  Remember it’s critical that your WinProc stays available to process incoming messages.  If it makes a blocking call or runs in a loop you will not be able to process incoming messages and your window will not repaint and your application will appear to be hung.

 

If you look deeper yet into the call stack you can see that the WndProc calls hangtype1, this calls gethostbyname.    http://msdn2.microsoft.com/en-us/library/ms738524.aspx 

 

Looking at the docs, Gethostbyname takes one parameter being the server name.  Looks dump it out and see what we are looking for.

 

0:000> kv 123

ChildEBP RetAddr  Args to Child             

0017ee14 76f584c5 00000424 40020000 004d9c60 ntdll!NtAlpcSendWaitReceivePort+0x12 (FPO: [8,0,0])

0017ee44 76f5899d 00020000 004d9c60 004e3638 rpcrt4!LRPC_CASSOCIATION::AlpcSendWaitReceivePort+0x2f (FPO: [Non-Fpo])

0017ee78 76f58514 0017eed8 0017ef04 0017f2e8 rpcrt4!LRPC_BASE_CCALL::DoSendReceive+0x48 (FPO: [Non-Fpo])

0017ee90 76f57785 0017eed8 0017ef04 0017eeb4 rpcrt4!LRPC_BASE_CCALL::SendReceive+0x2c (FPO: [Non-Fpo])

0017eea0 76f5766b 0017eed8 756e54f0 0017ef04 rpcrt4!I_RpcSendReceive+0x25 (FPO: [Non-Fpo])

0017eeb4 76f5763a 0017ef04 004d9d18 76ff0146 rpcrt4!NdrSendReceive+0x31

0017eec0 76ff0146 59a28201 00000000 00000000 rpcrt4!NdrpSendReceive+0x9 (FPO: [0,0,0])

0017f2c8 756e5ff3 756e54f0 756e5aec 0017f2e8 rpcrt4!NdrClientCall2+0x18f

0017f2e0 756e5ef9 00000000 0279091c 00000001 dnsapi!R_ResolverQuery+0x19 (FPO: [Non-Fpo])

0017f34c 756e5d34 0279091c 00000001 14000000 dnsapi!Query_PrivateExW+0x257 (FPO: [Non-Fpo])

0017f388 756e6025 00000001 0279091c 00000001 dnsapi!Query_Shim+0xbb (FPO: [Non-Fpo])

0017f3b0 74f461b4 0279091c 00000001 14000000 dnsapi!DnsQuery_W+0x20 (FPO: [Non-Fpo])

0017f3e0 74f4611c 0279091c 00000001 14000000 mswsock!SaBlob_Query+0x2d (FPO: [Non-Fpo])

0017f424 74f459db 0279091c 0031c2e0 00307118 mswsock!Rnr_DoDnsLookup+0x129 (FPO: [Non-Fpo])

0017f6c0 76d75a72 027908b8 00000000 0017f794 mswsock!Dns_NSPLookupServiceNext+0x25c (FPO: [Non-Fpo])

0017f6d8 76d75a52 00307270 027908b8 00000000 ws2_32!NSPROVIDER::NSPLookupServiceNext+0x17 (FPO: [Non-Fpo])

0017f6f4 76d75994 0031bc18 00000000 0017f794 ws2_32!NSPROVIDERSTATE::LookupServiceNext+0x1c (FPO: [Non-Fpo])

0017f720 76d7590a 00307130 00000000 0017f794 ws2_32!NSQUERY::LookupServiceNext+0xa4 (FPO: [Non-Fpo])

0017f764 76d7b11f 00307118 00000000 0017f794 ws2_32!WSALookupServiceNextW+0x74 (FPO: [Non-Fpo])

0017f7b4 76d7ab77 00307118 00000000 0017f7ec ws2_32!WSALookupServiceNextA+0x52 (FPO: [Non-Fpo])

0017f7e0 76d7dba3 00307118 0000013c 0017fa38 ws2_32!getxyDataEnt+0xbd (FPO: [Non-Fpo])

0017fa1c 0040147d 0017fa38 00000000 00070520 ws2_32!gethostbyname+0xb4 (FPO: [Non-Fpo])

0017fbc8 004012fc 00401220 0017fbfc 00401220 badwindow!hangtype1+0x3d (FPO: [Uses EBP] [0,101,0]) (CONV: cdecl) [c:\source\badwindow\badwindow\badwindow.cpp @ 310]

0017fc24 772a87af 00070520 00000111 00008003 badwindow!WndProc+0xdc (CONV: stdcall) [c:\source\badwindow\badwindow\badwindow.cpp @ 274]

0017fc50 772a8936 00401220 00070520 00000111 user32!InternalCallWinProc+0x23

0017fcc8 772a8a7d 00000000 00401220 00070520 user32!UserCallWinProcCheckWow+0x109 (FPO: [Non-Fpo])

0017fd2c 772a8ad0 00401220 00000000 0017ff0c user32!DispatchMessageWorker+0x380 (FPO: [Non-Fpo])

0017fd3c 004010fb 0017fd54 00403938 00000001 user32!DispatchMessageW+0xf (FPO: [Non-Fpo])

0017ff0c 00401817 00400000 00000000 004a0f84 badwindow!wWinMain+0xfb (CONV: stdcall) [c:\source\badwindow\badwindow\badwindow.cpp @ 124]

0017ffa0 76eb19f1 7efde000 0017ffec 7782d109 badwindow!__tmainCRTStartup+0x150 (FPO: [Non-Fpo]) (CONV: cdecl) [f:\sp\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 589]

0017ffac 7782d109 7efde000 0017206b 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [Non-Fpo])

0017ffec 00000000 00401987 7efde000 00000000 ntdll!_RtlUserThreadStart+0x23 (FPO: [Non-Fpo])

0:000> da 0017fa38

0017fa38  "AServerThatDoesNotExist14"

 

Generally speaking it’s not a good idea to make any call that could possibly block in your winproc. 

 

Let’s look deeper into what the caller (hangtype1) is really doing, Feel free to look at the C code as it was included with the project.  I like to look at the assembler,  it’s nice practice for those times you don’t have the source.  We can take the return address from the gethostbyname call 0040147d to figure out how it was called.  A neat trick for disassembling the entire function based on an address within that functions code range is to use the unassembled function or UF command.  In the following sample output I’ll simply UF the return address of the gethostbyname call.   I’ll then walk trough and annotate the disassembly.  Then we will look at the C source.

 

For reference on intel cpu programming see http://developer.intel.com/design/pentium/manuals/24319001.pdf

 

0:000> uf 0040147d

We are making run for locals on the stack, 402 dec bytes.  If you look at the source you will see this is a sznamebuff[400], int I, and pointer to a host structure.
badwindow!hangtype1 [c:\source\badwindow\badwindow\badwindow.cpp @ 298]:
298 00401440 81ec94010000    sub     esp,194h 

 

This is done for  stack checking to ensure none is trying to exploit our stack.
298 00401446 a100304000      mov     eax,dword ptr [badwindow!__security_cookie (00403000)]
298 0040144b 33c4            xor     eax,esp
298 0040144d 89842490010000  mov     dword ptr [esp+190h],eax

Save ebx register state on the stack
298 00401454 53              push    ebx 

Get the function pointer for sprint from the import table.
299 00401455 8b1d7c204000    mov     ebx,dword ptr [badwindow!_imp__sprintf (0040207c)]

Save the stack base / frame pointer.
299 0040145b 55              push    ebp

Get the address of gethostbyname from the import table and save it in EBP.
299 0040145c 8b2d20214000    mov     ebp,dword ptr [badwindow!_imp__gethostbyname (00402120)]

Save ESI and EDI on the stack.
299 00401462 56              push    esi
299 00401463 57              push    edi

Zero out ESI

299 00401464 33f6            xor     esi,esi
badwindow!hangtype1+0x26 [c:\source\badwindow\badwindow\badwindow.cpp @ 306]:

Push ESI on the stack and the first pass it will be zero == 0, this is the 3rd parameter to the call we are about to make.
306 00401466 56              push    esi

We are loading the effective address of something on the stack, we will see what it is used for when we use EAX, remember that.
306 00401467 8d442414        lea     eax,[esp+14h]

Hum what is this?.
badwindow!`string' (004021ac) Well when in doubt dump it out.
0:000> db 004021ac
004021ac  41 53 65 72 76 65 72 54-68 61 74 44 6f 65 73 4e  AServerThatDoesN
004021bc  6f 74 45 78 69 73 74 25-64 00 00 00 57 65 20 61  otExist%d...We a
004021cc  72 65 20 69 6e 20 68 61-6e 67 74 79 70 65 32 74  re in hangtype2t
004021dc  68 72 65 61 64 61 00 00-57 65 20 61 72 65 20 69  hreada..We are i
004021ec  6e 20 68 61 6e 67 74 79-70 65 32 74 68 72 65 61  n hangtype2threa
004021fc  64 62 00 00 48 00 00 00-00 00 00 00 00 00 00 00  db..H...........
0040220c  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
0040221c  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

Ok so we are pushing our print formatting string for sprintf this is the second parameter to the call we are about to make.

306 0040146b 68ac214000      push    offset badwindow!`string' (004021ac)

Ok here we are pushing EAX,  remember eax is just an address on our stack, and in this case the 1st parameter passed to sprint,  it’s our BUFFER.  szNameBuffer to be exact.
306 00401470 50              push    eax

 

Call sprint (Remember we stored it’s address in ebx)
306 00401471 ffd3            call    ebx

 

Stacks grown down or negative as they get larger, so adding in this case is cleaning up the stack from our sprintf call
306 00401473 83c40c          add     esp,0Ch

 

Get the address of the szNameBuffer
307 00401476 8d4c2410        lea     ecx,[esp+10h]

 

Push the address of the name buffer on the stack.
307 0040147a 51              push    ecx

 

Call gethostbyname (Rember we stored it’s address in ebp the)  NOTE when you do a return the value is stored in EAX (REMBER THIS)
307 0040147b ffd5            call    ebp

 

Push 250 dec FA hex on the stack.  (This is our return address from get host by name we see on the stack)
310 0040147d 68fa000000      push    0FAh 

 

Store EAX in EDI We need to save it because EAX will be over written when we come back from Sleep and we may want to use it later.  Eax is the return value from gethostbyname.
310 00401482 8bf8            mov     edi,eax

 

Call sleep it takes 1 parameter and that values was just pushed on the stack 250ms ¼ second.
310 00401484 ff150c204000    call    dword ptr [badwindow!_imp__Sleep (0040200c)]

Increment ESI this is where we are storing the value int i.   It was zero the first time through now it’s ESI+1 if we loop it will grow
311 0040148a 83c601          add     esi,1

 

Compare ESI we know this is in I to 0x64h or 100dec.
312 0040148d 83fe64          cmp     esi,64h

Where we have a jump if greater then, that is to say if ESI > 64h or 100dec jump to 00401496
312 00401490 7f04            jg      badwindow!hangtype1+0x56 (00401496)

Now we test EDI, this is the return value from gethostbyname.  TEST is a logical compare.  So if you test EDI and EDI and EDI = 0
304 00401492 85ff            test    edi,edi

If EDI is ZERO 0 jump to this address je is jump if ZERO this take us to the TOP of the loop.

304 00401494 74d0            je      badwindow!hangtype1+0x26 (00401466)

 

The rest of this is us cleaning up the stack and getting ready to drop out of the function.  We can stop here.
318 00401496 8b8c24a0010000  mov     ecx,dword ptr [esp+1A0h]
318 0040149d 5f              pop     edi
318 0040149e 5e              pop     esi
318 0040149f 5d              pop     ebp
318 004014a0 5b              pop     ebx
318 004014a1 33cc            xor     ecx,esp
318 004014a3 e8c5010000      call    badwindow!__security_check_cookie (0040166d)
318 004014a8 81c494010000    add     esp,194h
318 004014ae c3              ret

 

Here is the C code snipped for hangtype1

 

void hangtype1(void)

{

int i =0;

char szNameBuff[400];

struct hostent * myhost=NULL;

 

      // Lets see if any of my favorte machines are on the network.

      while (!myhost)

      {

            sprintf(szNameBuff,"AServerThatDoesNotExist%d",i);

            myhost = gethostbyname (szNameBuff);

            // We are hitting network resource in a loop.

            // Let's not hit the server with to many request at once. We will pause 250ms.

            Sleep(250);

            i++;

            if(i>100)

            {

                  break;

            }

      }

     

}

 

So what is happening,  if you recall we saw AServerThatDoesNotExist14 on the stack.  We know from this loop and the format string passed to sprint that this loop will run to 100 and will sleep 250ms with each pass.  That’s 25 seconds total just in sleeps not to mention the network stall on a bad server name.   I realize this code is somewhat contrived but it’s based on the types of things we actually see and troubleshoot every day.

 

So how do we get this work done without stalling the application?.  The answer is rather simple.  We go multithreaded.   You can look for hangtype1fix in the project.  Instread of calling hangtype1 from our windproc directly we declare a threadproc called hangtype1fixthread

 

void __cdecl hangtype1fixthread(void *)

{

       // our blocking function.

       hangtype1();

}

 

Then from our winproc instead of calling hangtype1 we call another function called hangtype1fix that creates a new thread that in turn executes out hangtype1 code in another thread context so our winproc can continue to execute and process incoming messages.  The being thread call is asynchronously .  The thread is create immediately and your thread continues to run.

 

void hangtype1fix(void)

{

       _beginthread(hangtype1fixthread, 12000, NULL);

}

 

I hope you found this blog informative and I welcome your feedback.

 

Thanks  Jeff-

 

 

Leave a Comment
  • Please add 3 and 6 and type the answer here:
  • Post
  • Small tip for people running this example:

    If you happen to be capturing the DMP on the second run, you'll need to do a "IPConfig /flushdns" (from an Admin Console) to get rid of your DNS Client cache. Otherwise, the gethostbyname call will be done in an instant and the Call Stack will just have you sitting on a Sleep.

    ;-)

    Andrew Richards

  • 이 문서는 http://blogs.msdn.com/ntdebugging blog 의 번역이며 원래의 자료가 통보 없이 변경될 수 있습니다. 이 자료는 법률적 보증이 없으며 의견을 주시기

Page 1 of 1 (2 items)