Thread overview
[phobos] More breakage in latest phobos
Jul 05, 2010
Walter Bright
Jul 05, 2010
Walter Bright
Jul 05, 2010
Walter Bright
July 05, 2010
Most likely a change in druntime broke this. Windows, obviously.

======================================================
..\dmd -g -d -ofmydll2.dll -version=use_patch mydll2.d dll2.d mydll2.def
std.contracts has been scheduled for deprecation. Please use
std.exception instead.

implib /system mydll2.lib mydll2.dll
Digital Mars Import Library Manager Version 8.41n
Copyright (C) Digital Mars 2000-2004 All Rights Reserved,
www.digitalmars.com
implib/h for help
Input is a Windows NT DLL file 'MYDLL2.DLL'.
Output is a Windows NT import library.
Digital Mars Import Library Creator complete.

..\dmd -g -d testmydll2.d mydll2.lib

testmydll2
hello dll world
hello dll world
---- hangs here ----
================== mydll2.d ==================
module mydll2;

import std.stdio;

version(D_Version2)
{
        import core.memory;
}
else
{
        import std.gc;
}

export void dllprint()
{
        writefln("hello dll world");
}

int glob;


// test access to (tls) globals
export int getglob()
{
        return glob;
}

// test gc-mem-allocation from different threads
export char* alloc(int sz)
{
        char* p = (new char[sz]).ptr;
version(D_Version2)
        GC.addRange(p, sz);
else
        addRange(p, p + sz);

        return p;
}

export void free(char* p, int sz)
{
version(D_Version2)
        GC.removeRange(p);
else
        removeRange(p);

        // delete p;
}
================== dll2.d =================
// Public Domain

import std.c.windows.windows;
import std.c.stdlib;

version(D_Version2)
{
    import core.runtime;
    import core.memory;
version(use_patch)
    import core.dll_helper;
    import core.stdc.string;

    extern (C) void _moduleTlsCtor();
    extern (C) void _moduleTlsDtor();
}
else
{
    import std.gc;
    import std.thread;

version(use_patch)
    import std.thread_helper;

    extern (C)
    {
    void gc_init();
    void gc_term();
    void _minit();
    void _moduleCtor();
    void _moduleDtor();
    void _moduleUnitTests();
    }
}

extern (Windows)
BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
{
    switch (ulReason)
    {
    case DLL_PROCESS_ATTACH:
version(D_Version2)
{
    version(use_patch)
    {
        if( !dll_fixTLS( hInstance, &_tlsstart, &_tlsend,
&_tls_callbacks_a, &_tls_index ) )
        return false;

        thread_setNeedLock(true);
        Runtime.initialize();

        // attach to all other threads
        enumProcessThreads( function (uint id, void* context) {
            if( !Thread.findThread( id ) )
            {
                thread_attach( id );
                thread_moduleTlsCtor( id );
            }
            return true;
        }, null );
    }
    else
        Runtime.initialize();
}
else
{
        gc_init();            // initialize GC
        _minit();            // initialize module list
        _moduleCtor();        // run module constructors
        _moduleUnitTests();        // run module unit tests

    version(use_patch)
    {
        // attach to all other threads
        enumProcessThreads( function (uint id, void* context) {
        if( !Thread._getThreadById( id ) )
            Thread.thread_attach( id, OpenThreadHandle( id ),
getThreadStackBottom( id ) );
        return true;
        }, null );
    }
//        enumThreads();
}
        break;

    case DLL_PROCESS_DETACH:
version(D_Version2)
{
    version(use_patch)
    {
        // detach from all other threads
        enumProcessThreads(
            function (uint id, void* context) {
                if( id != GetCurrentThreadId() && Thread.findThread( id ) )
                    thread_detach( id );
                return true;
            }, null );
    }
        Runtime.terminate();
}
else
{
    version(use_patch)
    {
        // detach from all other threads
        enumProcessThreads(
            function (uint id, void* context) {
                if( id != GetCurrentThreadId() )
                {
                    thread_moduleTlsDtor( id );
                    Thread.thread_detach( id );
                }
                return true;
            }, null );
    }
        _moduleDtor();
        gc_term();            // shut down GC
}
        break;

    case DLL_THREAD_ATTACH:
version(use_patch)
{
    version(D_Version2)
    {
            thread_attachThis();
            _moduleTlsCtor();
    }
    else
        Thread.thread_attach();
}
        break;

    case DLL_THREAD_DETACH:
version(use_patch)
{
    version(D_Version2)
    {
        if( Thread.findThread( GetCurrentThreadId() ) )
            _moduleTlsDtor();
        thread_detachThis();
    }
    else
        Thread.thread_detach();
}
        break;
    }
    return true;
}

====================== mydll2.def ================
LIBRARY "mydll2.dll"
EXETYPE NT
SUBSYSTEM WINDOWS
CODE SHARED EXECUTE
DATA WRITE

===================== testmydll2.d ===================

version(D_Version2)
{
    const string d2_shared = " __gshared ";
}
else
{
    const string d2_shared = "";
}

version(dynload)
{
    extern(Windows) void* LoadLibraryA(in char* dll);
    extern(Windows) void* GetProcAddress(void* lib, in char* name);

    typedef void fnDllPrint();
    typedef int fnGetglob();
    typedef char* fnAlloc(int sz);
    typedef void fnFree(char* p, int sz);

    mixin(d2_shared ~ "fnDllPrint* pDllPrint;");
    mixin(d2_shared ~ "fnGetglob* pGetglob;");
    mixin(d2_shared ~ "fnAlloc* pAlloc;");
    mixin(d2_shared ~ "fnFree* pFree;");

    int loadLib()
    {
       void* lib = LoadLibraryA("mydll2.dll".ptr);
       assert(lib);
       pDllPrint = cast(fnDllPrint*) GetProcAddress(lib,
"D6mydll28dllprintFZv".ptr);
         pFree = cast(fnFree*) GetProcAddress(lib,
"D6mydll24freeFPaiZv".ptr);
       pAlloc = cast(fnAlloc*) GetProcAddress(lib,
"D6mydll25allocFiZPa".ptr);
       pGetglob = cast(fnGetglob*) GetProcAddress(lib,
"D6mydll27getglobFZi".ptr);
       assert(pDllPrint && pFree && pAlloc && pGetglob);
       return 0;
    }

    void dllprint()
    {
        (*pDllPrint)();
    }

    int getglob()
    {
        return (*pGetglob)();
    }

    char* alloc(int sz)
    {
        return (*pAlloc)(sz);
    }
    void free(char* p, int sz)
    {
        (*pFree)(p, sz);
    }
}
else
{
    import mydll2;
}

mixin(d2_shared ~ "Object syncobj;");

void runtest()
{
    // wait until lib loaded
    synchronized(syncobj) getglob();

    //int g = mydll.glob;

    char*[] mem;
    for(int i = 0; i < 10000; i++)
    {
        mem ~= alloc(16);
    }
    for(int i = 0; i < 10000; i++)
    {
        free(mem[i], 16);
    }

    dllprint();
}

version(D_Version2)
{
    import core.thread;

    class TestThread : Thread
    {
        this()
        {
            super(&runtest);
        }
    }
}
else
{
    import std.thread;

    class TestThread : Thread
    {
        int run()
        {
            runtest();
            return 0;
        }
        void join()
        {
            wait();
        }
    }

}

void test_threaded()
{
    syncobj = new Object;
    TestThread[] th;

    for(int i = 0; i < 10; i++)
        th ~= new TestThread();

    // don't run threads before lib loaded
    synchronized(syncobj)
    {
        for(int i = 0; i < 5; i++)
            th[i].start();

        // create some threads before loading the lib, other later
        version(dynload) loadLib();
    }

    for(int i = 5; i < 10; i++)
        th[i].start();

    for(int i = 0; i < 10; i++)
        th[i].join();
}

int main()
{
   test_threaded();
   return 0;
}

===============================================

July 05, 2010

Walter Bright wrote:
> Most likely a change in druntime broke this. Windows, obviously.
>

Mix & match testing shows the breakage is somewhere in Phobos, not Druntime.
July 05, 2010

Walter Bright wrote:
>
>
> Walter Bright wrote:
>> Most likely a change in druntime broke this. Windows, obviously.
>>
>
> Mix & match testing shows the breakage is somewhere in Phobos, not Druntime.
>

Further testing shows that installing the latest std.format is breaking it.