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 |
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 |
Free forum by Nabble | Edit this page |