The following code works on dmd x64. Fails on dmd x32 and ldc x64. The problem is the passed variable.



import std.stdio;


version (Windows)
{
    import core.sys.windows.windows;

    void makeExecutable(ubyte[] code)
    {
        DWORD old;
VirtualProtect(code.ptr, code.length, PAGE_EXECUTE_READWRITE, &old);
    }
}
else
version (linux)
{
    import core.sys.posix.sys.mman;
    import core.sys.posix.unistd;

    static if (!is(typeof(&mprotect)))
        extern(C) int mprotect(void*, size_t, int);

    void makeExecutable(ubyte[] code)
    {
        auto pageSize = sysconf(_SC_PAGE_SIZE);
        auto address = ((cast(size_t)code.ptr) & ~(pageSize-1));
        int pageCount =
(address/pageSize == (address+code.length)/pageSize) ? 1 : 2;
        mprotect(cast(void*)address, pageSize * pageCount,
            PROT_READ | PROT_WRITE | PROT_EXEC);
    }
}
else
    static assert(0, "TODO");

R function(A) delegate2function(R, A...)(R delegate(A) d)
{
    enum size_t TEMPLATE1 = cast(size_t)0x01234567_01234567;
    enum size_t TEMPLATE2 = cast(size_t)0x89ABCDEF_89ABCDEF;

    static R functionTemplate(A args)
    {
        R delegate(A) d;
        d.ptr     = cast(typeof(d.ptr    ))TEMPLATE1;
        d.funcptr = cast(typeof(d.funcptr))TEMPLATE2;
        return d(args);
    }

    static void functionTemplateEnd() {}

    static void replaceWord(ubyte[] a, size_t from, size_t to)
    {
        foreach (i; 0..a.length - size_t.sizeof + 1)
        {
            auto p = cast(size_t*)(a.ptr + i);
            if (*p == from)
            {
                *p = to;
                return;
            }
        }
        assert(0);
    }

    auto templateStart = cast(ubyte*)&functionTemplate;
    auto templateEnd   = cast(ubyte*)&functionTemplateEnd;
auto templateBytes = templateStart[0 .. templateEnd - templateStart];

// must allocate type with pointers, otherwise GC won't scan it auto functionWords = new void*[(templateBytes.length / (void*).sizeof) + 3];

// store context in word-aligned boundary, so the GC can find it
    functionWords[0] = d.ptr;
    functionWords[1] = d.funcptr;
    functionWords = functionWords[2..$];

auto functionBytes = (cast(ubyte[])functionWords)[0..templateBytes.length];
    functionBytes[] = templateBytes[];

    replaceWord(functionBytes, TEMPLATE1, cast(size_t)d.ptr    );
    replaceWord(functionBytes, TEMPLATE2, cast(size_t)d.funcptr);
    makeExecutable(functionBytes);

    return cast(typeof(return)) functionBytes.ptr;
}




public struct sExtThread(T)
{
        uint Id = 0;
        HANDLE Handle;
        alias callbackType = extern (Windows) uint function(void*);     
        

public void Create(uint delegate(T) c, T param, bool suspended = false, uint stackSize = 16000)
        {       
Handle = CreateThread(cast(SECURITY_ATTRIBUTES*)null, stackSize, cast(callbackType)delegate2function(c), cast(void*)&param, (suspended) ? CREATE_SUSPENDED : 0, &Id);
        }

        
}



void main()
{
    import std.stdio;

        string q = "WTFSDFA";
        sExtThread!string t;
        t.Create((p)
        {
                writeln(q);
                writeln(p);
                return 1;
        }, "ASDFASDF");
        

        getchar();
}


p is invalid.

Obviously isn't not necessary to pass p but still, somethings wrong. I stole the delegate2function from Vladimir "The Propeller" Panteleev! Thanks Vlad!

It doesn't seem to be a problem with x86 since LDC x64 has the same problem(or writes junk I guess). Could be an issue with delegate2function but it's a bit over my head.

Reply via email to