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