From: Pete Gontier on 19 Jul 2006 19:42 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 19 Jul 2006 21:51 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 19 Jul 2006 22:54 * 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 20 Jul 2006 12:28 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 20 Jul 2006 16:18
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 >>> |