[D-runtime] druntime fixes again break Windows DLL support

Rainer Schuetze r.sagitario at gmx.de
Wed Apr 20 14:06:49 PDT 2011


Don Clugston wrote:
> On 20 April 2011 19:55, Sean Kelly <sean at invisibleduck.org> wrote:
>> On Apr 20, 2011, at 7:49 AM, Don Clugston wrote:
>>
>>> On 20 April 2011 16:22, Sean Kelly <sean at invisibleduck.org> wrote:
>>>> The helper modules were moved to core.sys.windows. I prepended an underscore because I thought they'd be for internal use. Alternate suggestions welcome.
>>> They're ugly and look like internal functions. I think just give them
>>> nice names.
>>>
>>> In fact, how about a wrapper function for the whole mess?
>>>
>>> extern (Windows)
>>> BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
>>> {
>>>     return standardDllMain(hInstance, ulReason);
>>> }
>>>
>>> Any other required work can be done after the standard handler.
>>> I make a lot of C-callable DLLs (in fact, it's ~75% of my D
>>> programming) and they're all like this.
>>> We might need a different wrapper for D-callable DLLs.
>> I hope that the same wrapper can be used for both.  It would stink if the DLL creator had to build with the intent of being used by D or non-D apps.
> 
> It is a decision you have to make right at the beginning.  If you have
> a D app, you can (in theory) pass gc-allocated memory through extern
> functions. If you have a non-D app, all memory management has to use
> memory allocated by Windows, and all extern functions have to be
> extern(C) or extern(Windows).
> So in the D case, the GC for the DLL and the GC for the app need to be
> connected, and it's far more complicated.


I agree. A DLL "connected" to a D app must not do any initialization in 
DllMain(PROCESS_ATTACH), because it has not received the gc-proxy yet. 
(There is some code in the proxy to move the ranges to scan to the 
application GC, but any object created during initialization lives on 
the wrong heap and will not be scanned or collected.)
On the other hand a "standalone" DLL must be initialized in DllMain, 
unless you want to add a lazy initialization check to every export that 
might get called, waiting for setProxy() being called first or not.

I guess, I repeat myself, but I don't think the GC-proxy mechanism is 
good enough. What if the DLL creates a thread? The app does not know 
about the new thread (won't suspend it in a GC collection), the GC does 
not scan the new TLS data segment of the DLL (it even does not get 
notified of the apps own new TLS segment). I think, there is more 
trouble lurking (e.g. socket initialization).

The best approach I see is to share the complete runtime in a DLL, so 
any executable or DLL can use shared or unshared memory, threads, etc. 
as defined by the interfaces between the binaries.


> 
>> So how about we rename windows._dll to windows.dll, and windows._thread to something else (dllthread? threadsupp?), then add the standardDllMain to windows.dll.
> 
> I'd like to hear Rainer's opinion on this --  I'd go along with
> anything he says.


Adding standardDllMain() sounds good to me. I agree with windows.dll, too.

I'm not so sure about windows._thread. OSX has an osx.mach.thread_act, 
so we might want to have a similar naming for windows, but I have no 
idea what "act" stands for here.

Looking through the code, it mostly deals with the thread environment 
block, so windows.teb might be ok, but not really obvious.

dllthread: the code has nothing to do with DLLs explicitely, so it would 
not fit.
threadsupp: maybe better: threadaux or threadhelp. The latter would at 
least match the naming of the dbghelp module.

Though not perfect, threadaux or threadhelp are my favorites.


More information about the D-runtime mailing list