Update
Further research showed that claims did not start using the Delphi host due to invalid configuration files. Once this was resolved, the Delphi host died as abruptly as the C # host.
Please note that all this is connected with 64-bit builds of XE2. We have already noticed that statements kill the 64-bit Delphi debugger, although they do not use the 32-bit platform.
Replacing AssertErrorProc and just executing some protocols there eliminates the situation for both the Delphi debugger and our C # and Delphi hosts.
Both hosts also survive by throwing exceptions in the place of statements. Exceptions are thrown with the exception of blocks that are in place.
The problem cannot be reproduced using Delphi XE3 (thanks to @David for helping with this), so the current status is that this is due to (error) handling of exceptions / statements in Delphi XE2, especially on a 64-bit platform.
I have a Delphi DLL that is designed to be called from a C # self-service web service. For debugging purposes, this DLL can also be called from the Delphi executable.
The DLL can be used successfully with both Delphi hosts and C #.
Today I came across a situation that caused a statement in the code executed during the initialization of the DLL, and found that this statement was unable to leave the DLL when it was placed in the Delphi process, but was not caught and forces the host die when it is a C # process.
Delphi dll
The Delphi DLL has its own DllProc procedure, which is called manually from dpr, because Delphi RTL "captures" the entry point to allow element initialization. See http://docwiki.embarcadero.com/VCL/XE/en/System.DLLProc for details.
Delphi dpr dll code:
begin DllProc := MyDllMain; MyDllMain(DLL_PROCESS_ATTACH); end.
The main user dll routine simply ensures that some structures are initialized when the DLL loads and exits when the last "bootloader" leaves.
procedure MyDllMain(Reason: Integer); begin // ... // DLL_PROCESS_ATTACH: begin if _RefCount < 1 then InitializeDLL; Inc(_RefCount); end; // ... end;
The InitializeDLL procedure is protected by a try except block that is specifically designed to prevent exceptions from being excluded from the DLL.
procedure InitializeDLL; begin try // Some code triggering an Assert(False, 'Whatever'); except on E: Exception do TLogger.LogException('InitializeDLL'); // Don't raise through. Exceptions should not leave DLL. end; end;
Delphic host
The Delphi host manually calls LoadLibrary for the Delphi DLL, extracts pointers to the functions it needs, and calls the DLL using them.
procedure InternalSetup; begin FLibrary := LoadLibrary(CLibraryPath); GetResource := GetProcAddress(FLibrary, 'GetResource'); PostResource := GetProcAddress(FLibrary, 'PostResource'); PutResource := GetProcAddress(FLibrary, 'PutResource'); DeleteResource := GetProcAddress(FLibrary, 'DeleteResource'); end;
Call: Result: = GetResource (INVALID_URI, {aQueryParams =} '', {out} ResponseBody);
C # host
C # host contains the following code to call the DLL
[DllImport("EAConfigurationEngine.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)] // Delphi: // function GetResource(aURI: string; aQueryParams: string; out aResponseBody: WideString): THTTPStatusCode; stdcall; export; private static extern int GetResource( string uri, string queryParams, [MarshalAs(UnmanagedType.BStr)] out string responseBody);
Question
As stated above, an exception block is thrown when the host for the DLL is a Delphi executable. However, when a call is made to the Delphi DLL from the C # host, assertion triggers, an unblocked block is not reached (the message is not logged, instead the uninitialized log logs an unhandled exception from the assertion), and the C # process dies when the "vshost.exe dialog stops working "
What causes this and how can I prevent it?