Mixed mode DLL and Loader Lock issue - revisited

R

Roy Chastain

I have read and re-read KB 814472. There appears to be a little 1984
New Speak in it.

I am referring to option 3.
DLL that contains consumers that use managed code and dll exports or
managed entry points

The minitialize and mterminate functions are straight forward and make
sense. The problem is with the code

BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID
lpvReserved) {
Console::WriteLine(S"DllMain is called...");
return TRUE;
} /* DllMain */


Now, this seems to me that this code violates the rule that no managed
code should be run under loader lock.

I have a c# main program.

static void Main(string[] args)
{
ManagedWrapperr.minitialize();
,,,,,
ManagedWrapperr.mterminate();
}

And to no surprise I see the following output
DllMain is called...
__crt_dll_initialize is called...

(I added the line Console::WriteLine(S"__crt_dll_initialize is
called...");
in minitialize after the call to __crt_dll_initialize.

I would assume that putting a managed dll in the references (or in the
#using list) would be the same as making it statically linked in
non-managed environment. If that is the case then how does this code
actually do us any good? (The implication being that the load caused
by the referencing managed code as in turn called to OS to do the DLL
load which as already called DLLMAIN which should have run the
non-managed dll initialize (__crt_dll_initialize).

Prior to putting the work around code into my dll, I did not have a
user defined DLLMAIN therefore my DLLMAIN should (I would expect) have
been unmanaged only, so why do I even get the loader lock problem to
start with?
 
B

Bart Jacobs

Roy,

Roy said:
I have read and re-read KB 814472. There appears to be a little 1984
New Speak in it.

I am referring to option 3.
DLL that contains consumers that use managed code and dll exports or
managed entry points

The minitialize and mterminate functions are straight forward and make
sense. The problem is with the code

BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID
lpvReserved) {
Console::WriteLine(S"DllMain is called...");
return TRUE;
} /* DllMain */


Now, this seems to me that this code violates the rule that no managed
code should be run under loader lock.

You are compiling this DLL using the /NOENTRY switch. Therefore the
DllMain function does not get called by the OS Loader. Therefore the
rule is not violated.
I have a c# main program.

static void Main(string[] args)
{
ManagedWrapperr.minitialize();
,,,,,
ManagedWrapperr.mterminate();
}

And to no surprise I see the following output
DllMain is called...
__crt_dll_initialize is called...

(I added the line Console::WriteLine(S"__crt_dll_initialize is
called...");
in minitialize after the call to __crt_dll_initialize.

The DllMain function gets called during your
ManagedWrapperr.minitialize() call, not when the DLL is loaded.
I would assume that putting a managed dll in the references (or in the
#using list) would be the same as making it statically linked in
non-managed environment. If that is the case then how does this code
actually do us any good? (The implication being that the load caused
by the referencing managed code as in turn called to OS to do the DLL
load which as already called DLLMAIN which should have run the
non-managed dll initialize (__crt_dll_initialize).

Could you rephrase this paragraph?
Prior to putting the work around code into my dll, I did not have a
user defined DLLMAIN therefore my DLLMAIN should (I would expect) have
been unmanaged only, so why do I even get the loader lock problem to
start with?

If you have a mixed DLL, VC++ always creates a DllMain that calls into
managed code.

See
<http://msdn.microsoft.com/library/d...stechart/html/vcconMixedDLLLoadingProblem.asp>.

In any case, it might be better to avoid mixed DLLs completely, by
splitting the Managed C++ project into a pure Win32 C++ project and a
C++ Class Library project. In the C# project, you can use P/Invoke and
pointer manipulation (using the "unsafe" keyword). The biggest
disadvantage of this is probably that you have to manually translate the
unmanaged function prototypes into P/Invoke method declarations. If your
unmanaged code is stable, this is doable, but if it evolves in parallel
with your managed code, it's a pain.

Bart Jacobs
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top