Board index » delphi » Fundamentally broken: Delphi DLL entry points.

Fundamentally broken: Delphi DLL entry points.

Hi folks,

Am I being stupid, or is the Delphi encapsulation of the DLL entry point
fundamentally broken?

To cut short a long and complicated story, I'm trying to demonstrate how
to write a multiprocess DLL for a new chapter in my tutorial. Basically,
because Delphi itself uses this procedure to driving initialization and
finalization of units etc, the programmer never gets first shot at using
it.

This has the following utterly broken effects (Under Delphi 4 at least):

1. If a DLL is loaded on program startup, and the hook proc is set in
the main DLL body, the programmer never sees the process and first
thread attachments.

2. If the DLL is loaded later on when the program has already spawned
multiple threads, *all* the initial thread attachments never get
recorded.

3. The final thread detach is never registered.

4. If the progam is quit without Waiting For TThread descendants, all
the final thread detachments are not registered.

As a result of points 1-4:

- It is impossible to write a multiprocess DLL containing global data
that keeps track of how many processes and threads have it loaded.

Now I've done this with no problem in visual C++, and I have no doubt
that this errant behaviour results from the initialization sequence of
Delphi DLL's.

1. Is it going to be fixed by offering a better encapsulation?
2. Is there a half way tenable work-around?

For interest, the DLL in question is contained in:

http://www.pergolesi.demon.co.uk/temp/Source49.html
http://www.pergolesi.demon.co.uk/temp/Source50.html

A program that *appears* to work with it is in:

http://www.pergolesi.demon.co.uk/temp/Source51.html
http://www.pergolesi.demon.co.uk/temp/Source52.html

A program that demonstrates it's a complete pile of crud is in:

http://www.pergolesi.demon.co.uk/temp/Source53.html

Try creating a few threads, and *then* loading the DLL.

Some useful narrative explaining my train of thought can be found at:

http://www.pergolesi.demon.co.uk/temp/Ch14.html

under the section "Writing a multiprocess DLL."

MH.

--
Martin Harvey. mar...@pergolesi.demon.co.uk
     http://www.pergolesi.demon.co.uk
               ICQ: 37298917

 

Re:Fundamentally broken: Delphi DLL entry points.


"Martin Harvey" <mar...@pergolesi.demon.co.uk> skrev i melding
news:39C2B0D6.F9EE70F0@pergolesi.demon.co.uk...

Quote

> Hi folks,

> Am I being stupid, or is the Delphi encapsulation of the DLL entry
point
> fundamentally broken?

> To cut short a long and complicated story, I'm trying to demonstrate
how
> to write a multiprocess DLL for a new chapter in my tutorial.
Basically,
> because Delphi itself uses this procedure to driving initialization
and
> finalization of units etc, the programmer never gets first shot at
using
> it.

> This has the following utterly broken effects (Under Delphi 4 at
least):

> 1. If a DLL is loaded on program startup, and the hook proc is set in
> the main DLL body, the programmer never sees the process and first
> thread attachments.

> 2. If the DLL is loaded later on when the program has already spawned
> multiple threads, *all* the initial thread attachments never get
> recorded.

That's excactly what I found out today, too. I wasn't about to use
multithreading, mainly interested in the DLL_PROCESS_DETACH, to free up
some form and datamodule.

Quote
> 3. The final thread detach is never registered.

Never tried it...

Quote
> 4. If the progam is quit without Waiting For TThread descendants, all
> the final thread detachments are not registered.

This may have another reason: When killing the process without freeing
the threads, you can't expect the .DLL to remain in memory until
"whenever-the-thread-is-finished", right ? The process that once mapped
the .DLL into its address space is since long gone. The .DLL should
perform nothing after this, I believe...

Quote
> As a result of points 1-4:

> - It is impossible to write a multiprocess DLL containing global data
> that keeps track of how many processes and threads have it loaded.

Isn't it possible to do some init code instead (initialization...end.) ?
To keep it clear, use the suggested workaround from Borland (see below)

Quote
> Now I've done this with no problem in visual C++, and I have no doubt
> that this errant behaviour results from the initialization sequence of
> Delphi DLL's.

> 1. Is it going to be fixed by offering a better encapsulation?
> 2. Is there a half way tenable work-around?

From Delphi 5 help file on "DLLProc":

Note: DLL_PROCESS_ATTACH is passed to the procedure only if the DLL's
initialization code calls the procedure and specifies DLL_PROCESS_ATTACH
as a parameter.

...the "fix" compared to D4 is the added "Note: " text....

One may wonder, sometimes, why assembly is available, while essential
stuff like this is hidden like you would hide a sharp knife from a
baby...

Bjoerge Saether
Consultant / Developer
Asker, Norway
bsaether.removet...@online.no (remove the obvious)

Re:Fundamentally broken: Delphi DLL entry points.


Quote
"Bj?rge S?ther" wrote:

> That's excactly what I found out today, too. I wasn't about to use
> multithreading, mainly interested in the DLL_PROCESS_DETACH, to free up
> some form and datamodule.

Interesting ... Jon Shemitz was complaining about problems with ExitProc
in borland.public.delphi.objectpascal, basically explaining that
ExitProc never got called in exceptional situations, and they tie in
well with both of our experiences.

Although I don't have any code to look at, I'm fast getting a mental
model of how Delphi uses these calls to drive it's own initialization,
and as a result, why it *necessarily* can't pass all the info to the
application programmer.

Quote
> > 4. If the progam is quit without Waiting For TThread descendants, all
> > the final thread detachments are not registered.

> This may have another reason: When killing the process without freeing
> the threads, you can't expect the .DLL to remain in memory until
> "whenever-the-thread-is-finished", right ?

But I'm not *killing* the process. I'm just clicking the close button in
the top right, and letting Delphi do whatever it normally does when
there are several TThread descandants running. Does it actually force
kill the threads?

Quote
> The process that once mapped
> the .DLL into its address space is since long gone. The .DLL should
> perform nothing after this, I believe...

For the reasons mentioned above ... it should really be a fairly
organised exit.

Quote
> Isn't it possible to do some init code instead (initialization...end.) ?

Unfortunately not, because at DLL load time, I can't determine how many
threads are running in the app. *All* the initial attachments at DLL
load time get ditched :-(

Quote
> To keep it clear, use the suggested workaround from Borland (see below)

Unfortunately, that workaround is insufficient, it only fixes  the
process half the startup problem, which I have fixed anyway. The other
half (keeping track of threads) appears to be impossible :-(

Quote
> One may wonder, sometimes, why assembly is available, while essential
> stuff like this is hidden like you would hide a sharp knife from a
> baby...

Because the Borland encapsulation has some very subtle implications
which are *by design*.

Anyway, I've just about figured why this happens:

- If writing a *raw* entry point function (eg in C), the info is
*statically compiled* into the DLL, and it'll get called in all cases.

- If writing an *encapsulated* entry point function, ie in Delphi, the
problem is that the function you or I write is pointed to by a
*variable*, and since that variable is set up in the DLL main body,
which is driven by the initial process attach, it *can't* be set up soon
enough to register the inital process attachment.

It's essentially a chicken and egg problem, and I can't see a
workaround. Still, I'm surprised that it doesn't pick up the fact that
multiple threads may exist at initialisation time.

MH.

--
Martin Harvey. mar...@pergolesi.demon.co.uk
     http://www.pergolesi.demon.co.uk
               ICQ: 37298917

Re:Fundamentally broken: Delphi DLL entry points.


"Martin Harvey" <mar...@pergolesi.demon.co.uk> skrev i melding
news:39C2C463.530AC40E@pergolesi.demon.co.uk...

Quote
> "Bj?rge S?ther" wrote:

> > That's excactly what I found out today, too. I wasn't about to use
> > multithreading, mainly interested in the DLL_PROCESS_DETACH, to free
up
> > some form and datamodule.

> Interesting ... Jon Shemitz was complaining about problems with
ExitProc
> in borland.public.delphi.objectpascal, basically explaining that
> ExitProc never got called in exceptional situations, and they tie in
> well with both of our experiences.

> Although I don't have any code to look at, I'm fast getting a mental
> model of how Delphi uses these calls to drive it's own initialization,
> and as a result, why it *necessarily* can't pass all the info to the
> application programmer.

From what I can see, the DLLProc is run before unit initialization, so
how could you possibly specify a DllProc that was to be called at
startup time ?

Quote
> > > 4. If the progam is quit without Waiting For TThread descendants,
all
> > > the final thread detachments are not registered.

> > This may have another reason: When killing the process without
freeing
> > the threads, you can't expect the .DLL to remain in memory until
> > "whenever-the-thread-is-finished", right ?

> But I'm not *killing* the process. I'm just clicking the close button
in
> the top right, and letting Delphi do whatever it normally does when
> there are several TThread descandants running. Does it actually force
> kill the threads?

The question would be if the threads ever get to finish their execution
before the process is stopped. To my experience, this is not allways the
case - the OS may act pretty funny after half a day with programming
multithreaded apps ;-) While an application's threads are (attempted, at
least) stopped upon process exit, it may be too late for a graceful
exit - possibly also failing to reach the DLLEntryPoint proc af an
attached .DLL. Shutting down a multithreaded app without noise is
possibly one of the hardest programming tasks in standard Windows
programming..;-)

I've never seen a good explaination on what happens when a "thread
stampede" is remaining after the process is killed. *Is* the process
killed, then, or just unreachable ? May a thread actually cause any CPU
instructions to be run after the process is stopped ? Well, when chicken
can run after getting their heads axed off, a "ghost" thread should be
able to at least cause an AV or two..;-)

Quote
> > The process that once mapped
> > the .DLL into its address space is since long gone. The .DLL should
> > perform nothing after this, I believe...

> For the reasons mentioned above ... it should really be a fairly
> organised exit.

> > Isn't it possible to do some init code instead

(initialization...end.) ?

Quote

> Unfortunately not, because at DLL load time, I can't determine how
many
> threads are running in the app. *All* the initial attachments at DLL
> load time get ditched :-(

I checked system.pas today, and it's fairly clear, I guess: Unit
initialization is run after the DLLProc. You won't ever get to set the
procedure address in time.

[...]

Quote
> Because the Borland encapsulation has some very subtle implications
> which are *by design*.

> Anyway, I've just about figured why this happens:

> - If writing a *raw* entry point function (eg in C), the info is
> *statically compiled* into the DLL, and it'll get called in all cases.

> - If writing an *encapsulated* entry point function, ie in Delphi, the
> problem is that the function you or I write is pointed to by a
> *variable*, and since that variable is set up in the DLL main body,
> which is driven by the initial process attach, it *can't* be set up
soon
> enough to register the inital process attachment.

Ahhh, seems reasonable...a weird kind of DLLProc documentation problem -
"this is of limited use as it's not a full{*word*76}ed DLLEntryProc - no need
for much documentation, then "

Quote
> It's essentially a chicken and egg problem, and I can't see a
> workaround. Still, I'm surprised that it doesn't pick up the fact that
> multiple threads may exist at initialisation time.

I must say I don't understand how multiple threads will attach to the
.dll upon initialization ? Does the loading process kinda "register" all
its running threads with the .DLL ?

...er, no, it doesn't (looked up the help file on "DLLEntryPoint":
"..Note that a DLL's entry-point function is called with this value only
by threads created after the DLL is attached to the process. When a DLL
is attached by LoadLibrary, existing threads do not call the entry-point
function of the newly loaded DLL."

So, the DLL_THREAD_ATTACH event should be (surprisingly, at least) lost
lost only if a thread was started after the DllEntryPoint proc is
called, but before the unit initialization. Isn't this a marginal
problem, as you'll have to handle the allready existing threads as
well.. ?

Very interesting, Martin !
--
Bjoerge Saether
Consultant / Developer
Asker, Norway
bsaether.removet...@online.no (remove the obvious)

Re:Fundamentally broken: Delphi DLL entry points.


Ahhh... thanks to your reply and a quick look in Win32.hlp, everything
is now perfectly clear.

Quote
"Bj?rge S?ther" wrote:
> From what I can see, the DLLProc is run before unit initialization, so
> how could you possibly specify a DllProc that was to be called at
> startup time ?

...

Quote
> I checked system.pas today, and it's fairly clear, I guess: Unit
> initialization is run after the DLLProc. You won't ever get to set the
> procedure address in time.

...

Quote
> Ahhh, seems reasonable...a weird kind of DLLProc documentation problem -
> "this is of limited use as it's not a full{*word*76}ed DLLEntryProc - no need
> for much documentation, then "

Okay, so effectively, the source of my worries comes in two categories.
This is number (1): that you'll never get the initial process
attachment. As such, it is not a problem, you just assume in in the
initialization or main DLL body that a process is attaching. Fine.

Quote
> I must say I don't understand how multiple threads will attach to the
> .dll upon initialization ? Does the loading process kinda "register" all
> its running threads with the .DLL ?

I was hoping that this would be the case, since it would allow one to
keep a count of exactly how many threads are in the DLL. However, this
doesn't happen, and it is effectively operating system behaviour that
determines that it doesn't happen.

Thre reason it doesn't happen is this (from Win32.hlp).

"DLL_THREAD_ATTACH
Indicates that the current process is creating a new thread. When this
occurs, the system calls the entry-point function of all DLLs currently
attached to the process. NOTE: The call is made in the context of the
new thread."

Since the existing threads are minding their own business, it's not
possible to call the EntryProc in the context of the particular threads
that are already running, hence it doesn't happen.

Myself, I'd be happy to just have the entry proc called several times,
once for each thread running at load time, with all the calls being made
in the context of the thread that loaded the library.

Quote
> So, the DLL_THREAD_ATTACH event should be (surprisingly, at least) lost
> lost only if a thread was started after the DllEntryPoint proc is
> called, but before the unit initialization. Isn't this a marginal
> problem, as you'll have to handle the allready existing threads as
> well.. ?

You are correct, it's a marginal problem. One area of conflict does
occur however:

Once a DLL's initialization code has set up the entrypoint,
initalization code after that moment may be executed concurrently whilst
another thread executes the entry point function itself. As a result,
the DLL entry point should always be set up
*last* during DLL initialization.

Quote
> > > > 4. If the progam is quit without Waiting For TThread descendants,
> all
> > > > the final thread detachments are not registered.

> > > This may have another reason: When killing the process without
> freeing
> > > the threads, you can't expect the .DLL to remain in memory until
> > > "whenever-the-thread-is-finished", right ?

Again, this is a thread context thing. If the DLL_THREAD_DETACH was
called from the context of the thread that unloaded the library (or in
the context of an OS cleanup thread), then this would be possible.
However, given the fact that all events occur in the context of the
thread that they pertain to, you are correct in saying that this is not
possible.

Quote
> Very interesting, Martin !

I now understand everything, and it's all quite clear to me. However,
it's considerably more subtle than I thought at first glance.

MH.

--
Martin Harvey. mar...@pergolesi.demon.co.uk
     http://www.pergolesi.demon.co.uk
               ICQ: 37298917

Re:Fundamentally broken: Delphi DLL entry points.


Quote
David Reeve wrote:

> Now this seems to solve the problems I had with getting threads
> to terminate cleanly ( I gave up with WaitFor. Its behaviour is too
> indeterminate for my liking).

Interesting. I've always preferred WaitFor, since I've been able to
*prove* the pleasant behaviour of the app.

Quote
> therefore the app. may well  shed its core DLLs while my thread is still
> running.

I suspect this depends on the RTL. Win32 will not close a process when
it has any threads running. The order in which the Delphi code force
quits threads and unloads DLL's is vital.

I preferred D2, because it wouldn't close threads behind your back. You
*had* to let all your threads come to a half way decent stop, and if
they wouldn't, then task manager was the only way.

Quote
>  However, I'm guessing how the OS works. It seems to me there is
> only one thread of execution involved in shutting down an app., which
> proceeds from DLL to DLL executing the exit procedure of each in turn.

The calls to DLLProc are done within the context of the appropriate
thread. If you don't put calls to LoadLibrary and FreeLibrary in a
TThread descendant, then this will be the case.

Quote
> Thus
> if you explicitly unload your DLL first, all will be OK.

Yes, provided your DLL remembers to shut everything down when it gets a
DLL_PROCESS_DETACH.

Quote
> Aplogies if this had degenerated into a bit of a ramble, and is slightly off
> topic, but I've been meaning to post this for some time.

No problem. Anyway, my conclusions are all in my multithreaded
programming guide now.

MH.

--
Martin Harvey. mar...@pergolesi.demon.co.uk
     http://www.pergolesi.demon.co.uk
               ICQ: 37298917

Re:Fundamentally broken: Delphi DLL entry points.


Quote
> > > > 4. If the progam is quit without Waiting For TThread descendants,
> all
> > > > the final thread detachments are not registered.

> > > This may have another reason: When killing the process without
> freeing
> > > the threads, you can't expect the .DLL to remain in memory until
> > > "whenever-the-thread-is-finished", right ?

> > But I'm not *killing* the process. I'm just clicking the close button
> in
> > the top right, and letting Delphi do whatever it normally does when
> > there are several TThread descandants running. Does it actually force
> > kill the threads?

> The question would be if the threads ever get to finish their execution
> before the process is stopped. To my experience, this is not allways the
> case - the OS may act pretty funny after half a day with programming
> multithreaded apps ;-) While an application's threads are (attempted, at
> least) stopped upon process exit, it may be too late for a graceful
> exit - possibly also failing to reach the DLLEntryPoint proc af an
> attached .DLL. Shutting down a multithreaded app without noise is
> possibly one of the hardest programming tasks in standard Windows
> programming..;-)

> I've never seen a good explaination on what happens when a "thread
> stampede" is remaining after the process is killed. *Is* the process
> killed, then, or just unreachable ? May a thread actually cause any CPU
> instructions to be run after the process is stopped ? Well, when chicken
> can run after getting their heads axed off, a "ghost" thread should be
> able to at least cause an AV or two..;-)

I've had my share of grief in this department. I'm frequently confronted
with the need to kill of a number crunching thread or two running in a DLL
when the application is forcibly closed. You can write code, and it seems to
work just fine, no AVs on close, resource checker shows everything
deallocated nicely, but, as Bjorge says, after half a day or so of work you
notice the OS is getting pretty tetchy.

What really winds me up is if you make some apparently quite unrelated
changes some months later, then back come the AVs on exit. I have since
noticed that you can have an app. close apparently successfully, but if you
look with the Win98  SystemTools|SystemInformation you see that the app. is
still registered, and also the DLL. If you rerun the program, you get
another copy stuck in the system.

However, I have a method that seems to work. In my DLL_PROCESS_DETACH code,
I set a flag to cause my number crunching loops to abort, call Terminate,
put up a message box to say we're closing, and then wait typically as long
as a second. Now this seems to solve the problems I had with getting threads
to terminate cleanly ( I gave up with WaitFor. Its behaviour is too
indeterminate for my liking). However, it brought with it AVs on close.
These I reckon, with my vague understanding of the OS, arise because the
app. has unloaded various DLLs, probably core functions, well before my
thread has terminated. Thus, if it then makes a call to an address space
recently vacated by a core DLL, we get an AV. I suspect, if you get an AV
its your lucky day, whats worse is to run on thinking the code is OK when in
fact its in a potentially unstable state.

Now, if in the app. I intercept the close,  and explicitly unload the the
DLL, all runs just fine. You could argue that the process time between my
intercepting the close and the normal OS process termination which follows
is very much less than the 1 sec delay I force in the exit of my DLL, and
therefore the app. may well  shed its core DLLs while my thread is still
running.  However, I'm guessing how the OS works. It seems to me there is
only one thread of execution involved in shutting down an app., which
proceeds from DLL to DLL executing the exit procedure of each in turn. Thus
if you explicitly unload your DLL first, all will be OK.

Aplogies if this had degenerated into a bit of a ramble, and is slightly off
topic, but I've been meaning to post this for some time.

Dave

- Show quoted text -

Quote
> > > The process that once mapped
> > > the .DLL into its address space is since long gone. The .DLL should
> > > perform nothing after this, I believe...

> > For the reasons mentioned above ... it should really be a fairly
> > organised exit.

Re:Fundamentally broken: Delphi DLL entry points.


The _ATTACH and _DETACH entry points were clearly architected just to
enable a DLL to set up and remove attachment-specific data structures
(e.g. those all-important shared-memory mappings) without "failing to be
notified of" a change in the status of a particular attachment.  It is,
in effect, a guaranteed initialize/terminate call-sequence, completely
asynchronous but nonetheless "guaranteed by Windows."  (Now, that and
25-cents will ... oh anyway.)

The architects obviously were not thinking about notification of the
DLL's other attached clients.  Rather, they were thinking about
"notifying the DLL itself," so to speak.

Quote
>Martin Harvey wrote:

> Ahhh... thanks to your reply and a quick look in Win32.hlp, everything
> is now perfectly clear.

> "Bj?rge S?ther" wrote:

> > From what I can see, the DLLProc is run before unit initialization, so
> > how could you possibly specify a DllProc that was to be called at
> > startup time ?

> ...

> > I checked system.pas today, and it's fairly clear, I guess: Unit
> > initialization is run after the DLLProc. You won't ever get to set the
> > procedure address in time.

> ...

> > Ahhh, seems reasonable...a weird kind of DLLProc documentation problem -
> > "this is of limited use as it's not a full{*word*76}ed DLLEntryProc - no need
> > for much documentation, then "

> Okay, so effectively, the source of my worries comes in two categories.
> This is number (1): that you'll never get the initial process
> attachment. As such, it is not a problem, you just assume in in the
> initialization or main DLL body that a process is attaching. Fine.

> > I must say I don't understand how multiple threads will attach to the
> > .dll upon initialization ? Does the loading process kinda "register" all
> > its running threads with the .DLL ?

> I was hoping that this would be the case, since it would allow one to
> keep a count of exactly how many threads are in the DLL. However, this
> doesn't happen, and it is effectively operating system behaviour that
> determines that it doesn't happen.

> Thre reason it doesn't happen is this (from Win32.hlp).

> "DLL_THREAD_ATTACH
> Indicates that the current process is creating a new thread. When this
> occurs, the system calls the entry-point function of all DLLs currently
> attached to the process. NOTE: The call is made in the context of the
> new thread."

> Since the existing threads are minding their own business, it's not
> possible to call the EntryProc in the context of the particular threads
> that are already running, hence it doesn't happen.

> Myself, I'd be happy to just have the entry proc called several times,
> once for each thread running at load time, with all the calls being made
> in the context of the thread that loaded the library.

> > So, the DLL_THREAD_ATTACH event should be (surprisingly, at least) lost
> > lost only if a thread was started after the DllEntryPoint proc is
> > called, but before the unit initialization. Isn't this a marginal
> > problem, as you'll have to handle the allready existing threads as
> > well.. ?

> You are correct, it's a marginal problem. One area of conflict does
> occur however:

> Once a DLL's initialization code has set up the entrypoint,
> initalization code after that moment may be executed concurrently whilst
> another thread executes the entry point function itself. As a result,
> the DLL entry point should always be set up
> *last* during DLL initialization.

> > > > > 4. If the progam is quit without Waiting For TThread descendants,
> > all
> > > > > the final thread detachments are not registered.

> > > > This may have another reason: When killing the process without
> > freeing
> > > > the threads, you can't expect the .DLL to remain in memory until
> > > > "whenever-the-thread-is-finished", right ?

> Again, this is a thread context thing. If the DLL_THREAD_DETACH was
> called from the context of the thread that unloaded the library (or in
> the context of an OS cleanup thread), then this would be possible.
> However, given the fact that all events occur in the context of the
> thread that they pertain to, you are correct in saying that this is not
> possible.

> > Very interesting, Martin !

> I now understand everything, and it's all quite clear to me. However,
> it's considerably more subtle than I thought at first glance.

> MH.

> --
> Martin Harvey. mar...@pergolesi.demon.co.uk
>      http://www.pergolesi.demon.co.uk
>                ICQ: 37298917

--
------------------------------------------------------------------
Sundial Services :: Scottsdale, AZ (USA) :: (480) 946-8259
mailto:i...@sundialservices.com  (PGP public key available.)

- Show quoted text -

Quote
> Fast(!), automatic table-repair with two clicks of the mouse!
> ChimneySweep(R):  "Click click, it's fixed!" {tm}
> http://www.sundialservices.com/products/chimneysweep

Re:Fundamentally broken: Delphi DLL entry points.


Quote
Martin Harvey <mar...@pergolesi.demon.co.uk> wrote in message

news:39C3F70C.5D4E41C@pergolesi.demon.co.uk...
Quote
> David Reeve wrote:

> > Now this seems to solve the problems I had with getting threads
> > to terminate cleanly ( I gave up with WaitFor. Its behaviour is too
> > indeterminate for my liking).

> Interesting. I've always preferred WaitFor, since I've been able to
> *prove* the pleasant behaviour of the app.

My problems are always to do with shutting down threads that run for
seconds. Thus if I tell my thread to terminate and then use WaitFor to hold
the main process in the DLL_PROCESS_DETACH code of the DLL, while the thread
shuts down, then sometimes it is OK and sometimes it deadlocks.  However,
this call to WaitFor is at a point when the app. is closing, which brings us
back to the question of how Delphi is handling finalization. I guess its not
so much difficult, as unknown!!

Quote
> > therefore the app. may well  shed its core DLLs while my thread is still
> > running.

> I suspect this depends on the RTL. Win32 will not close a process when
> it has any threads running. The order in which the Delphi code force
> quits threads and unloads DLL's is vital.

Yep that makes sense.

Quote

> I preferred D2, because it wouldn't close threads behind your back. You
> *had* to let all your threads come to a half way decent stop, and if
> they wouldn't, then task manager was the only way.

Thats interesting, because I certainly noted a difference when I moved some
D2 apps up to D4. I put it down to my inexperience when I wrote the D2 code,
and, hey, I really know what I'm doing now..... really!

Quote
> >  However, I'm guessing how the OS works. It seems to me there is
> > only one thread of execution involved in shutting down an app., which
> > proceeds from DLL to DLL executing the exit procedure of each in turn.

> The calls to DLLProc are done within the context of the appropriate
> thread. If you don't put calls to LoadLibrary and FreeLibrary in a
> TThread descendant, then this will be the case.

> > Thus
> > if you explicitly unload your DLL first, all will be OK.

> Yes, provided your DLL remembers to shut everything down when it gets a
> DLL_PROCESS_DETACH.

Yes this all makes sense.

Quote
> > Aplogies if this had degenerated into a bit of a ramble, and is slightly
off
> > topic, but I've been meaning to post this for some time.

> No problem. Anyway, my conclusions are all in my multithreaded
> programming guide now.

Thanks for your comments and I look forward to the next edition.

Dave

Quote

> MH.

> --
> Martin Harvey. mar...@pergolesi.demon.co.uk
>      http://www.pergolesi.demon.co.uk
>                ICQ: 37298917

Other Threads