Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Deadly embrace between SetUnhandledExceptionFilter() and thread rundown(???) in Server 2003

56 views
Skip to first unread message

j_3...@yahoo.com

unread,
Jan 4, 2010, 6:16:25 PM1/4/10
to
When our application starts up we call SetUnhandledExceptionFIlter()
and save off the address it returns as the current exception handler.
When we're exiting we pass this saved value back into
SetUnhandledExceptionFIlter() to re-establish the exception handler
that existed before we started. We also start a couple of threads.

Very occasionally we find that we don't shut down cleanly and if we
take a look with the debugger we find two thread in the process with
the following call stacks. It appears there is some kind of deadly
embrace in the use of critical sections between the code in
SetUnhandledExceptionFilter() and whatever code the other thread is
running (probably as part of thread cleanup but we're not sure).

This is Windows Server 2003 R2 SP2 (Enterprise Edition).

Does anyone know whether this is a known problem? Something which has
been fixed perhaps in Server 2008?

Thread #1:
0 > 3520 Main Thread Main Thread _unlock Normal 0
0 3200 Worker Thread Win32 Thread 7c82860c Normal 0
ntdll.dll!_ZwWaitForSingleObject@12() + 0xc bytes
ntdll.dll!_RtlpWaitOnCriticalSection@8() - 0xe4 bytes
ntdll.dll!_RtlEnterCriticalSection@4() + 0x22f51 bytes
ntdll.dll!_LdrLockLoaderLock@12() + 0x6b bytes
kernel32.dll!_GetModuleFileNameW@12() + 0x51 bytes
kernel32.dll!_FillUEFInfo@8() + 0x4d bytes
> kernel32.dll!_SetUnhandledExceptionFilter@4() + 0x2b bytes
<user program calls SetUnhandledExceptionFilter()>
<user program frames>
digger.exe!__tmainCRTStartup() Line 586 + 0x17 bytes C
kernel32.dll!_BaseProcessStart@4() + 0x23 bytes

Thread #2:
0 3520 Main Thread Main Thread _unlock Normal 0
0 > 3200 Worker Thread Win32 Thread 7c82860c Normal 0
ntdll.dll!_KiFastSystemCallRet@0()
ntdll.dll!_ZwWaitForSingleObject@12() + 0xc bytes
ntdll.dll!_RtlpWaitOnCriticalSection@8() - 0xe4 bytes
ntdll.dll!_RtlEnterCriticalSection@4() + 0x22f51 bytes
> ntdll.dll!_LdrpInitializeThread@4() + 0x47 bytes
ntdll.dll!__LdrpInitialize@12() + 0x56 bytes
ntdll.dll!_KiUserApcDispatcher@16() + 0x25 bytes
<top of stack>

Jochen Kalmbach [MVP]

unread,
Jan 5, 2010, 3:14:46 AM1/5/10
to
Hi j_3140!

> When our application starts up we call SetUnhandledExceptionFIlter()
> and save off the address it returns as the current exception handler.
> When we're exiting we pass this saved value back into
> SetUnhandledExceptionFIlter() to re-establish the exception handler
> that existed before we started. We also start a couple of threads.

IMHO there is no need to restore the original handler...

--
Greetings
Jochen

My blog about Win32 and .NET
http://blog.kalmbachnet.de/

Joey

unread,
Jan 6, 2010, 11:07:59 AM1/6/10
to
On Jan 5, 3:14 am, "Jochen Kalmbach [MVP]" <nospam-n...@kalmbach-

software.de> wrote:
>
> IMHO there is no need to restore the original handler...
>
> --

Thank you for the suggestion.

We included this code because we may be loaded as a DLL by some
other software package which may have a handler of its own and we are
trying to be a good citizen and leave the process state the same as
we
found it.

I suppose we could just remove this call to SetUnhandledExceptionFilter
()
but that still leaves a question as to whether there is some bug
here in the kernel which needs to be fixed. In general this kind of
deadly embrace is because someone has messed up the order of
acquisition of resources so the two threads are blocking each other.

Pavel Lebedinsky [MSFT]

unread,
Jan 7, 2010, 2:23:34 AM1/7/10
to

> Thread #1:

> ntdll.dll!_RtlEnterCriticalSection@4() + 0x22f51 bytes
> ntdll.dll!_LdrLockLoaderLock@12() + 0x6b bytes
> kernel32.dll!_GetModuleFileNameW@12() + 0x51 bytes
> kernel32.dll!_FillUEFInfo@8() + 0x4d bytes
>> kernel32.dll!_SetUnhandledExceptionFilter@4() + 0x2b bytes
>
> Thread #2:

> ntdll.dll!_RtlpWaitOnCriticalSection@8() - 0xe4 bytes
> ntdll.dll!_RtlEnterCriticalSection@4() + 0x22f51 bytes
>> ntdll.dll!_LdrpInitializeThread@4() + 0x47 bytes
> ntdll.dll!__LdrpInitialize@12() + 0x56 bytes

To me it looks like both of these threads are blocked on the loader
lock. Can you check which thread owns it? In windbg/cdb you can
use the following command to do this:

0:000> !cs ntdll!LdrpLoaderLock

--
Pavel Lebedinsky/Windows Fundamentals Test
This posting is provided "AS IS" with no warranties, and confers no rights.


m

unread,
Jan 8, 2010, 9:16:51 PM1/8/10
to
In my experience, several of the Windows DLLs do not shutdown cleanly
(specifically DNS APIs and others) and a call to ExitProcess from the main
thread is necessary. This is usually performed by the CRT when Main
returns, but may not be for some special applications. IMHO, the shutdown
logic is less well tested and debugged in Windows than the other APIs.

<j_3...@yahoo.com> wrote in message
news:2340b5b1-382a-4285...@f5g2000yqh.googlegroups.com...

Jonathan de Boyne Pollard

unread,
Jan 11, 2010, 9:20:45 AM1/11/10
to

In my experience, several of the Windows DLLs do not shutdown cleanly (specifically DNS APIs and others)  and a call to ExitProcess from the main thread is necessary. 

I suggest that you read the aforelinked, too.  (-:



m

unread,
Jan 19, 2010, 7:42:49 PM1/19/10
to
Uh - why?
 
The behaviour is easy to reproduce: create an application that does not use the CRT, or any other ENV, call certain APIs on some versions of Windows, and return from your entry point.  The process will not die because ExitProcess was NOT called from the CRT wrapper code and there are running threads.  To work around this problem, ensure that ExitProcess is always called.
 
As good programming practice, one should always clean up resources, including exiting worker threads, before process exit.
 

Jonathan de Boyne Pollard

unread,
Jan 19, 2010, 10:58:56 PM1/19/10
to

In my experience, several of the Windows DLLs do not shutdown cleanly (specifically DNS APIs and others)  and a call to ExitProcess from the main thread is necessary. 

I suggest that you read the aforelinked, too.  (-:

Uh - why?

Because you'll find it edifying and interesting.

m

unread,
Jan 20, 2010, 10:33:54 PM1/20/10
to
And I did!  They are interesting articles no doubt
 
BTW: I am sorry that I misinterpreted your previous post. 

Jonathan de Boyne Pollard

unread,
Jan 21, 2010, 12:42:25 PM1/21/10
to

>
>
> BTW: I am sorry that I misinterpreted your previous post.
>
No worries.


0 new messages