From: Pete Gontier on
I'm trying to build a control panel DLL. Everything goes swimmingly until
it's time to close. It seems some part of the close cannot complete even
after my panel receives the appropriate messages (CPL_EXIT and
DLL_PROCESS_DETACH among others). "rundll32.exe" just hangs around,
presumably waiting for something else to happen.

From deep inside my spooky, mysterious, cavernous mind, I got an intuition
that the "something else" might be a thread which has not yet exited. Sure
enough, my DllMain function does receive a DLL_THREAD_ATTACH message but no
corresponding DLL_THREAD_DETACH message. My control panel does not create
any threads explicitly. Even more puzzling is that other control panels to
which I have the source -- and in fact that I myself wrote -- do not cause
any such thread to be created and do not have this problem, and I have been
unable to determine what this new panel is doing differently.

The thread gets created under two circumstances I've found so far.

I first noticed this problem when I added a manifest resource with ID 123 to
make the common controls DLL version 6 available to my panel. So the thread
might be created by this DLL or some DLL on which it depends. The question
is why? My other panels have an almost identical manifest resource
(differing only in the name of the assembly identity and its description).
If I renumber this resource to something other than 123, I don't have this
thread problem (and my program fails when it tries to send a message to a
tool tip window, so I know the common controls DLL has not loaded).

I've also noticed a problem thread being created when I explicitly load
"Msftedit.dll", the rich text control DLL, with a call to LoadLibrary. I do
this in several other panels without a thread being created.

Either one these circumstances leads to the creation of a problem thread. I
don't know that it's the same thread in both cases, but the fact that I get
only one problem thread when I both have a manifest and load the rich text
DLL suggests to me that the thread is being created by some DLL on which
both the common controls DLL and the rich text DLL depend.

If I knew how to track down who was creating this thread, I might have a
better sense of the conditions by which it is created and avoid those
conditions, but my debugging-fu is just not strong enough. I may only need
to be told how to set a breakpoint on CreateThread. (I am an old MacsBug
freak, so if by some truly odd chance you could explain this to me from that
perspective, it would help.)

Alternatively, if you happen to know what this thread is already and what
I've done wrong such that it gets created, I wouldn't need the debugging
instruction, which would save us both time. :-)

Any insight appreciated.

From: Pete Gontier on
On the advice of some folks off-list, I downloaded, installed, and futzed
around with SysInternals Process Explorer, which in turn recommended I
download the Microsoft driver debugging toolkit, which I did. I can now look
at some data about about the problem thread. Pressing the Stack button
produces this:

ntoskrnl.exe!ExReleaseResourceLite+0x206
ntoskrnl.exe!KeFlushQueuedDpcs+0x1fde
ntoskrnl.exe!KeFlushQueuedDpcs+0x314c
ntoskrnl.exe!IoCheckFunctionAccess+0x2f855
ntoskrnl.exe!RtlInsertElementGenericTableAvl+0x2b0
ntoskrnl.exe!Kei386EoiHelper+0x1d9
!DllMain+0x11b
!_DllMainCRTStartup+0xbb
ntdll.dll!LdrInitializeThunk+0x29
ntdll.dll!CsrNewThread+0xeb
ntdll.dll!RtlUnicodeStringToInteger+0x17d
ntdll.dll!KiUserApcDispatcher+0x7

I took this stack snapshot when the thread in question was stopped at a
breakpoint in my panel DLL having been sent the DLL_THREAD_ATTACH message. I
don't know if this info is helpful to anyone, but I thought I'd pass it
along just in case.

There's also a highly attractive Module button, which for some threads
produces the name of a DLL, presumably the DLL which created the thread (or
perhaps the name of the DLL which contains the thread entry proc, which
might be good enough). Unfortunately, for the problem thread, this button
reports only that the module could not be located. Talk about building me up
just to knock me down! :-)


On 7/19/06 4:42 PM, in article
C0E4118A.1CA4F%kokorozashi(a)discussions.microsoft.com, "Pete Gontier"
<kokorozashi(a)discussions.microsoft.com> wrote:

> I'm trying to build a control panel DLL. Everything goes swimmingly until
> it's time to close. It seems some part of the close cannot complete even
> after my panel receives the appropriate messages (CPL_EXIT and
> DLL_PROCESS_DETACH among others). "rundll32.exe" just hangs around,
> presumably waiting for something else to happen.
>
> From deep inside my spooky, mysterious, cavernous mind, I got an intuition
> that the "something else" might be a thread which has not yet exited. Sure
> enough, my DllMain function does receive a DLL_THREAD_ATTACH message but no
> corresponding DLL_THREAD_DETACH message. My control panel does not create
> any threads explicitly. Even more puzzling is that other control panels to
> which I have the source -- and in fact that I myself wrote -- do not cause
> any such thread to be created and do not have this problem, and I have been
> unable to determine what this new panel is doing differently.
>
> The thread gets created under two circumstances I've found so far.
>
> I first noticed this problem when I added a manifest resource with ID 123 to
> make the common controls DLL version 6 available to my panel. So the thread
> might be created by this DLL or some DLL on which it depends. The question
> is why? My other panels have an almost identical manifest resource
> (differing only in the name of the assembly identity and its description).
> If I renumber this resource to something other than 123, I don't have this
> thread problem (and my program fails when it tries to send a message to a
> tool tip window, so I know the common controls DLL has not loaded).
>
> I've also noticed a problem thread being created when I explicitly load
> "Msftedit.dll", the rich text control DLL, with a call to LoadLibrary. I do
> this in several other panels without a thread being created.
>
> Either one these circumstances leads to the creation of a problem thread. I
> don't know that it's the same thread in both cases, but the fact that I get
> only one problem thread when I both have a manifest and load the rich text
> DLL suggests to me that the thread is being created by some DLL on which
> both the common controls DLL and the rich text DLL depend.
>
> If I knew how to track down who was creating this thread, I might have a
> better sense of the conditions by which it is created and avoid those
> conditions, but my debugging-fu is just not strong enough. I may only need
> to be told how to set a breakpoint on CreateThread. (I am an old MacsBug
> freak, so if by some truly odd chance you could explain this to me from that
> perspective, it would help.)
>
> Alternatively, if you happen to know what this thread is already and what
> I've done wrong such that it gets created, I wouldn't need the debugging
> instruction, which would save us both time. :-)
>
> Any insight appreciated.
>


From: Alf P. Steinbach on
* Pete Gontier:
> [mystery thread appearing in control panel applet using XP look]

It's possibly related to side-by-side assembly execution, which is used
for the common controls DLL, and more probably anyway related to the
common controls DLL.

If you don't already, try calling InitCommonControls.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
From: Pete Gontier on
On 7/19/06 7:54 PM, in article 4i89jrF2kmjlU1(a)individual.net, "Alf P.
Steinbach" <alfps(a)start.no> wrote:

>> [mystery thread appearing in control panel applet using XP look]

> It's possibly related to side-by-side assembly execution, which is used for
> the common controls DLL, and more probably anyway related to the common
> controls DLL. If you don't already, try calling InitCommonControls.

I did already, but after you mentioned it I tried doing it earlier on the
chance that it might need to happen before loading "Msftedit.dll". This did
not help.

From: Pete Gontier on
The response below prompted me to do some investigation by which I solved
the problem.

The documentation for GdiplusStartup and GdiplusShutdown says you may not
call either function during DllMain, although it seems nothing bad happens
if you call the former during DllMain. What the documentation for these
calls doesn't explain is that the DllMain you write is not the DllMain it's
talking about. In fact, the real DllMain is in the C runtime library, and it
spoofs the messages before they get to your DllMain. Among other things the
C runtime library does during DllMain is construct and destruct global
objects. If one of these globals happens to have a constructor which calls
GdiplusStartup and a destructor which calls GdiplusShutdown, the DLL will
block endlessly in GdiplusShutdown waiting for a thread created by
GdiplusStartup to exit. The thread will never exit because only one thread
at a time can run while a DLL is being torn down. This apparently isn't a
problem for a regular application (EXE), presumably because its C runtime
library works differently. (I ran into this problem while converting an
application to a panel.)

To solve this problem, I moved the object in question onto the stack. This
should work regardless of whether the code is compiled into an application
or a DLL. It means I might not use memory in the most efficient possible way
because I'm unable to create some GDI+ objects globally, but the alternative
was much worse. :-)


On 7/20/06 10:28 AM, in article ebRdrICrGHA.4424(a)TK2MSFTNGP05.phx.gbl, "Code
Jockey" <gimme(a)the.keyboard> wrote:

> During process shutdown, global static objects with destructors that wait
> for threads to exit can cause an application to hang, because only one
> thread at a time is allowed to run at that time.
>
> Problems like this can be caused by an architecture where DllMain() calls
> functions that cause other modules to get loaded, or create threads, and
> wait for threads at unload time. If the constructors of global static
> objects do similar things, then the same problems can result, because these
> actually run before DllMain(). .
>
> Modules that cause this kind of dead-lock can be loaded and unloaded
> dynamically during normal app runtime conditions and avoid the hang.
>
>
>
> "Pete Gontier" <kokorozashi(a)discussions.microsoft.com> wrote in message
> news:C0E42FBB.1CA6D%kokorozashi(a)discussions.microsoft.com...
>> On the advice of some folks off-list, I downloaded, installed, and futzed
>> around with SysInternals Process Explorer, which in turn recommended I
>> download the Microsoft driver debugging toolkit, which I did. I can now
> look
>> at some data about about the problem thread. Pressing the Stack button
>> produces this:
>>
>> ntoskrnl.exe!ExReleaseResourceLite+0x206
>> ntoskrnl.exe!KeFlushQueuedDpcs+0x1fde
>> ntoskrnl.exe!KeFlushQueuedDpcs+0x314c
>> ntoskrnl.exe!IoCheckFunctionAccess+0x2f855
>> ntoskrnl.exe!RtlInsertElementGenericTableAvl+0x2b0
>> ntoskrnl.exe!Kei386EoiHelper+0x1d9
>> !DllMain+0x11b
>> !_DllMainCRTStartup+0xbb
>> ntdll.dll!LdrInitializeThunk+0x29
>> ntdll.dll!CsrNewThread+0xeb
>> ntdll.dll!RtlUnicodeStringToInteger+0x17d
>> ntdll.dll!KiUserApcDispatcher+0x7
>>
>> I took this stack snapshot when the thread in question was stopped at a
>> breakpoint in my panel DLL having been sent the DLL_THREAD_ATTACH message.
> I
>> don't know if this info is helpful to anyone, but I thought I'd pass it
>> along just in case.
>>
>> There's also a highly attractive Module button, which for some threads
>> produces the name of a DLL, presumably the DLL which created the thread
> (or
>> perhaps the name of the DLL which contains the thread entry proc, which
>> might be good enough). Unfortunately, for the problem thread, this button
>> reports only that the module could not be located. Talk about building me
> up
>> just to knock me down! :-)
>>
>>
>> On 7/19/06 4:42 PM, in article
>> C0E4118A.1CA4F%kokorozashi(a)discussions.microsoft.com, "Pete Gontier"
>> <kokorozashi(a)discussions.microsoft.com> wrote:
>>
>>> I'm trying to build a control panel DLL. Everything goes swimmingly
> until
>>> it's time to close. It seems some part of the close cannot complete even
>>> after my panel receives the appropriate messages (CPL_EXIT and
>>> DLL_PROCESS_DETACH among others). "rundll32.exe" just hangs around,
>>> presumably waiting for something else to happen.
>>>
>>> From deep inside my spooky, mysterious, cavernous mind, I got an
> intuition
>>> that the "something else" might be a thread which has not yet exited.
> Sure
>>> enough, my DllMain function does receive a DLL_THREAD_ATTACH message but
> no
>>> corresponding DLL_THREAD_DETACH message. My control panel does not
> create
>>> any threads explicitly. Even more puzzling is that other control panels
> to
>>> which I have the source -- and in fact that I myself wrote -- do not
> cause
>>> any such thread to be created and do not have this problem, and I have
> been
>>> unable to determine what this new panel is doing differently.
>>>
>>> The thread gets created under two circumstances I've found so far.
>>>
>>> I first noticed this problem when I added a manifest resource with ID
> 123 to
>>> make the common controls DLL version 6 available to my panel. So the
> thread
>>> might be created by this DLL or some DLL on which it depends. The
> question
>>> is why? My other panels have an almost identical manifest resource
>>> (differing only in the name of the assembly identity and its
> description).
>>> If I renumber this resource to something other than 123, I don't have
> this
>>> thread problem (and my program fails when it tries to send a message to
> a
>>> tool tip window, so I know the common controls DLL has not loaded).
>>>
>>> I've also noticed a problem thread being created when I explicitly load
>>> "Msftedit.dll", the rich text control DLL, with a call to LoadLibrary. I
> do
>>> this in several other panels without a thread being created.
>>>
>>> Either one these circumstances leads to the creation of a problem
> thread. I
>>> don't know that it's the same thread in both cases, but the fact that I
> get
>>> only one problem thread when I both have a manifest and load the rich
> text
>>> DLL suggests to me that the thread is being created by some DLL on which
>>>