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

Terminating a thread during DLL unload

1,206 views
Skip to first unread message

Will Barker

unread,
May 15, 2000, 3:00:00 AM5/15/00
to
Anyone got any good techniques for terminating a thread at
DLL_PROCESS_DETACH time?

Essentially, if your DLL has the need for a thread to do its job then, in my
case, the thread is ideally started, on behalf of the calling process,
during DLL_PROCESS_ATTACH. The DLL entry-points can then be called until the
process wants to exit , at which point DllMain is called with
DLL_PROCESS_DETACH. Unfortunately, at this stage, you cannot wait for events
etc. so how do you terminate the thread. Even the NT4 audio driver sample
suffers in this respect and has the following comment :

//
// This is all wrong - we need to find out how to terminate threads !
//

Of course, I could have an entry point in the DLL which must be called
before the process exits, during which I can wait on the thread handle for
the thread to exit. Unfortunately this is not a viable solution since I am
dealing with a fixed, legacy interface.

will....@iname.com

Peter A. Kirk

unread,
May 15, 2000, 3:00:00 AM5/15/00
to
Hi there
do you really *have* to wait for your thread to exit before you continue
processing? You can just order your thread to terminate and then continue in
DLL_PROCESS_DETACH.

I don't actually know if there is a solution to this problem. I have faced the
same issue but have solved it by implementing an "un-initialise" routine which
the calling application needs to call before unloading the dll. Then I can do a
"wait" in my un-initialise routine. Of course, then you have to ensure that the
calling application isn't actually calling "un-initialise" from another dll's
process detach....

Otherwise, in situations like yours where I was dealing with a "legacy"
application, my only other solution was to order the thread to terminate and not
wait to see if it did terminate.

I would be grateful to hear of any better solution you come up with.

Peter.

Will Barker

unread,
May 15, 2000, 3:00:00 AM5/15/00
to
My concern is memory & resources leaks. Whether this is a "real" problem is
not absolutely clear at the moment - BoundsChecker claims it is. The main
problem is that the thread is processing blocks of memory that are allocated
within a DLL entry point and that are freed by the thread when processing is
complete. If the thread does not exit gracefully then the leak may well
occur. BC certainly complains about not closing the thread and event handles
used by the thread - even though they are closed at DLL_PROCESS_DETACH time.


Peter A. Kirk wrote in message <391FFF0A...@iccc.dk>...

Chris Becke

unread,
May 15, 2000, 3:00:00 AM5/15/00
to
> My concern is memory & resources leaks. Whether this is a "real" problem
is
> not absolutely clear at the moment - BoundsChecker claims it is. The main
> problem is that the thread is processing blocks of memory that are
allocated
> within a DLL entry point and that are freed by the thread when processing
is
> complete. If the thread does not exit gracefully then the leak may well
> occur. BC certainly complains about not closing the thread and event
handles
> used by the thread - even though they are closed at DLL_PROCESS_DETACH
time.

1. Any cleanup done at dll_process_detach time is likley to be missed by BC.
The system does not guarantee the order in which dll's will get
dll_process_detach messages when the process is closing - thus it is quite
likley that the BC hook dll's that do the monitoring will be closed before
your dll is terminated thus "missing" the good and proper cleanup of
resources.

2. BCs bitching notwithstanding, at process shutdown _everything_ is cleaned
up for you. Unless you have persisent data that may be corrupted if threads
are not cleaned up synchronously its actually generally quite safe to simply
allow the system to terminate the threads and clean up the processes
objects.

3. Conversely - if you recieve a dll_process_detach due to a FreeLibrary
(rather than process shutdown) and your dll has "live" threads within it,
they will cause faults when next they are scheduled.

4. The "uninitialize function" option is the safest, and is used by a number
of system dll's. OLE & Winsock come to mind.

5. You cannot:
5.1 signal the thread to exit, and let it exit in its own time as the dll
will be unmapped whn next it executes causing an exception, or
5.2 signal the thread to exit and wait for it to exit as you are very likley
to cause a deadlock situation, so
5.3 The only viable option for Dll's that maintain internal worker threads
is to call TerminateThread() on any threads they have in response to
process_detach.

If the calling application calls LoadLibrary / FreeLibarary repeatedly in a
loop this will cause memory leaks.

Finally, I finish :) There are two cases when you recieve process_detach

1. The process is being shut down. Really: don't wory about this situation -
the system will terminate the threads and cleanup memory - BC is just being
retentive.

2. The app called "FreeLibrary" on the dll. You can either:
2.1 *ignore* te issue by documenting that the dll will leak if shutdown and
loaded repeatedly, or
2.2 Make a shim dll that you pass to the application. This dll implements
the legacy interface as the application sees it. It passes all calls through
to a 2nd dll that contains the worker thread. When the "interface" dll is
freed you handle the dll_process_detach and use that to signal a handle in
the 2nd dll that the worker thread watches for. The worker thread can then
clean up anything that needs cleaning and exit using the
FreeLibraryAndExitThread API which was designed for just this situation.

Chris.
--
VisualC++ & Win32 FAQ: http://www.mvps.org/vcfaq
My Win32 Page: http://www.mvps.org/user32


keithmo

unread,
May 15, 2000, 3:00:00 AM5/15/00
to
A couple of issues worth mentioning:

1. Creating a thread during a DLL notification may not work exactly as
expected. Since DLL initialization routines are single-threaded, the new
thread's start routine will not begin execution until the current thread
"unwinds" out of the DLL notification. (Think about it this way. If you
create a worker thread in a DLL_PROCESS_ATTACH notification, the worker
thread cannot issue the DLL_THREAD_ATTACH while the current thread is still
processing the process attach.)

2. Likewise, if you request a worker thread to kill itself (say, by
signalling an event) from within a DLL notification, the thread will not
become "fully terminated" (i.e. the thread handle will not become signalled)
until the current thread "unwinds" out of the DLL notification.

Here's one way to use worker threads from within a DLL:

1. Before you create the worker thread (this could be during
DLL_PROCESS_ATTACH, but it's better do defer this until it's actually
needed), use GetModuleFileName() and LoadLibrary() to add an "artificial"
reference to the DLL. This will keep the DLL from disappearing from
"beneath" the worker thread. You will need to either pass the DLL's module
handle to the worker thread, or store it away in a global.

2. When it's time to kill the worker thread, signal an event (or use
whatever mechanism you need to tell the worker thread to kill itself). If
you're doing this from within a DLL attach/detach notification, then *do
not* wait for the thread to die, or you will deadlock.

3. The last thing the worker thread should do is call
FreeLibraryAndExitThread(). This will remove the artificial DLL reference
and terminate the worker thread. Since the thread will terminate during this
call, it will not have a chance to return back to the (possibly freed) DLL.


I've used this technique a number of times. It works great.


KM

"Will Barker" <will....@farsite.co.uk> wrote in message
news:8fotth$630$1...@ayers.ftech.net...

0 new messages