Strange behavior of VM with Delphi COM Servers.

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Strange behavior of VM with Delphi COM Servers.

juanvp
Hi,

I've been tracking for some time an access violation on process
termination when using an in-process COM Server written in Delphi from
the Dolphin VM.  This problem is only present when executing the
Lagoon-deployed exe, as when working with the development environment
the COM Server doesn't seem to be freed. What I've concluded is that
there is something unusual with the contexts under which the DllMain
procedure is called (under Delphi this procedure is called _InitLib in
unit sysinit.pas). One of the parameters of this proc is dfwReason
which takes the values: (DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH,
DLL_THREAD_ATTACH, DLL_THREAD_DETACH).
I've created a barebones COM Server, and deployed a Dolphin app which
only had a SessionManager subclass whose instance just created an
instance from this server. After tracing through the DllMain calls I
raliably get this sequence:
Call 1 -  fdwReason = DLL_PROCESS_ATTACH   (GetCurrentThreadID -> n1)
Call 2 -  fdwReason = DLL_THREAD_ATTACH   (GetCurrentThreadID -> n2)
Call 3 -  fdwReason = DLL_THREAD_DETACH   (GetCurrentThreadID -> n1)
Call 4 -  fdwReason = DLL_PROCESS_DETACH   (GetCurrentThreadID -> n1)

So, it would seem that the thread for the first detach is the wrong
one. And this causes an exception because Delphi tries to free a TLS
allocated memory twice, or tries to access a threadvar after the first
detach in the context of that thread. I've worked around the problem
touching the base Delphi RTL kernel, but I don't think this is a good
idea in the long run. Does anyone  happen to know why does this
strange context sequence happen?
I assume the Dolphin VM has something to do with this because when
creating a COM client in Delphi calls 2 and 3 are never made.

If anyone wants to take a look I can send the barebones projects that
reproduces the problem.

thanks
Juan Vidal Pich


Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior of VM with Delphi COM Servers.

Blair McGlashan
Juan

You in message news:[hidden email]...

>
> I've been tracking for some time an access violation on process
> termination when using an in-process COM Server written in Delphi from
> the Dolphin VM.  This problem is only present when executing the
> Lagoon-deployed exe, as when working with the development environment
> the COM Server doesn't seem to be freed. What I've concluded is that
> there is something unusual with the contexts under which the DllMain
> procedure is called (under Delphi this procedure is called _InitLib in
> unit sysinit.pas). One of the parameters of this proc is dfwReason
> which takes the values: (DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH,
> DLL_THREAD_ATTACH, DLL_THREAD_DETACH).
> I've created a barebones COM Server, and deployed a Dolphin app which
> only had a SessionManager subclass whose instance just created an
> instance from this server. After tracing through the DllMain calls I
> raliably get this sequence:
> Call 1 -  fdwReason = DLL_PROCESS_ATTACH   (GetCurrentThreadID -> n1)
> Call 2 -  fdwReason = DLL_THREAD_ATTACH   (GetCurrentThreadID -> n2)
> Call 3 -  fdwReason = DLL_THREAD_DETACH   (GetCurrentThreadID -> n1)
> Call 4 -  fdwReason = DLL_PROCESS_DETACH   (GetCurrentThreadID -> n1)
>
> So, it would seem that the thread for the first detach is the wrong
> one. And this causes an exception because Delphi tries to free a TLS
> allocated memory twice, or tries to access a threadvar after the first
> detach in the context of that thread. I've worked around the problem
> touching the base Delphi RTL kernel, but I don't think this is a good
> idea in the long run. Does anyone  happen to know why does this
> strange context sequence happen?

Well ultimately it is up to Windows how it calls DllMain. I'm not sure how
Dolphin could cause it to wrongly call DllMain with both DLL_THREAD_DETACH
and DLL_PROCESS_DETACH for the same thread.

The Win32 help states that "A thread calling the DLL entry-point function
with DLL_PROCESS_ATTACH does not call the DLL entry-point function with
DLL_THREAD_ATTACH" (so you wouldn't expect a DLL_THREAD_ATTACH for n1), and
that "... there are cases in which the entry-point function is called for a
terminating thred even if the DLL never attached to the thread..." (?), and
"Note that the thread that receives the DLL_PROCESS_DETACH notification is
not necessarily the same thread that received the DLL_PROCESS_ATTACH
function." Lastly, "When a DLL is unloaded from a process as a result of an
unsuccessful load of the DLL, termination of the process, or a call to
FreeLibrary, the system does not call the DLL's entry point function with
the DLL_THREAD_DETACH value for the individual theads of the process. The
DLL is only sent a DLL_PROCESS_DETACH notification."

Considering how loosely it is all specified, I'm not sure the sequence of
calls you list above is necessarily invalid (although common sense suggests
it is wrong). Even if it is, it is not necessarily in Dolphin's direct
control. Dolphin creates threads directly, and indirectly via the use of
certain Windows APIs (e.g. the multimedia timer), so there will be multiple
threads, some of which may have been created before the COM server has been
loaded, and some not. Other components and APIs are also free to create
their own threads. These threads may not be terminated in the same order
they were created.

> I assume the Dolphin VM has something to do with this ...

Certainly the conditions created by the Dolphin VM may have something to do
with this, but I'm not convinced it is directly responsible. Dolphin may
create and terminate threads, but it is up to Windows to call DllMain.
Alternative causes might be an obscure bug in Windows (have you tried using
NT/2k vs Win9X?), or perhaps Delphi's library is not defensively enough
coded to handle the unpredictable ordering.

>...because when
> creating a COM client in Delphi calls 2 and 3 are never made.

Does your Delphin COM client have more than one thread?

Regards

Blair