Cannot get thread ID with Thread.getThis() in specific callback functions on Windows

Rainer Schuetze r.sagitario at gmx.de
Thu Dec 9 12:14:58 PST 2010


A DLL gets notified in its entrypoint DllMain about new threads. When it 
receives such a notification, it mainly does the following:

             if( !thread_findByAddr( GetCurrentThreadId() ) )
                 thread_attachThis();
             if( !_moduleinfo_tlsdtors_i ) // avoid duplicate calls
                 _moduleTlsCtor();

You might want to try inserting this snippet into your callback.

Rainer

Haruki Shigemori wrote:
> (2010/12/07 20:02), Max Samukha wrote:
>> On 12/06/2010 10:47 PM, Mike Parker wrote:
>>> On 12/7/2010 2:10 AM, Haruki Shigemori wrote:
>>>> (2010/12/06 16:59), Denis Koroskin wrote:
>>>>> Because D runtime doesn't know about the newly created thread, and
>>>>> static constructors weren't called. Try calling the following in your
>>>>> callbacks:
>>>>>
>>>>> if (Thread.getThis() is null) thread_attachThis(); // if
>>>>> (dont_know_about_this_thread) initialize_it();
>>>>
>>>> Wow... Is this D's design?
>>>> I want phobos or druntime to take care of this problem.
>>>> Is it difficult?
>>>
>>> The problem is that the thread is created outside of druntime, internal
>>> to the Windows API. How is druntime to know about it unless you tell it?
>>
>> This could be done by installing a kernel driver that would use
>> PsSetCreateThreadNotifyRoutine (if I remember the name correctly) to
>> register a callback that would use an IPC mechanism to notify druntime
>> about new threads created by the system. Chances that this approach will
>> be adopted by druntime are less than zero.
> 
> As you said, it seems difficult to run away from this problem.
> But, this problem causes the phenomenon that is hard to reappear.
> 
> import win32.windows;
> import win32.mmsystem;
> import std.stdio;
> import core.thread;
> 
> extern (Windows)
> void waveInProc(in HWAVEIN handle, in uint message, in DWORD instance, 
> in DWORD param1, in DWORD param2)
> {
>     int[] a;
>     int[] b = a.dup; // Access violation occurs in druntime rarely.
> 
>     //auto tid = Thread.getThis();
>     //assert(tid); // assertion failure
> }
> 
> void main()
> {
>     foreach (_; 0..1000) // many times
>     {
>         WAVEFORMATEX formatEx;
>         with (formatEx)
>         {
>                 wFormatTag = WAVE_FORMAT_PCM;
>                 nChannels = 1;
>                 nSamplesPerSec = 44100;
>                 wBitsPerSample = 16;
>                 nBlockAlign = cast(ushort)(wBitsPerSample * nChannels / 8);
>                 nAvgBytesPerSec = nSamplesPerSec * nBlockAlign;
>         }
> 
>         HWAVEIN handle;
>         waveInOpen(&handle, WAVE_MAPPER, cast(WAVEFORMATEX*)&formatEx, 
> cast(DWORD)&waveInProc, cast(DWORD)null, CALLBACK_FUNCTION);
> 
>         uint bufferSize = cast(uint)(formatEx.nAvgBytesPerSec * 
> 1/+second+/);
>         WAVEHDR* hdr = new WAVEHDR;
>         hdr.lpData = cast(LPSTR)new ushort[bufferSize];
>         hdr.dwBufferLength = bufferSize;
>         hdr.dwFlags = 0;
>         hdr.dwLoops = 0;
> 
>         waveInPrepareHeader(handle, hdr, WAVEHDR.sizeof);
>         waveInAddBuffer(handle, hdr, WAVEHDR.sizeof);
>         waveInStart(handle);
> 
>         waveInClose(handle);
>     }
> }
> 
> Because the following "t" is null in core.thread.getThis rarely.
> Why? I think that we should react to this problem.
> 
> core.thread.d(1214): t = thread_findByAddr( GetCurrentThreadId() );


More information about the Digitalmars-d mailing list