Do I have to call TlsAlloc() in DLL_PROCESS_ATTACH once genrally since the DLL hasn't any addional calls with DLL_THREAD_ATTACH for the thread doing the LoadLibrary() ?
Or to make it even more complicated: Do I get a DLL_THREAD_ATTACH notification in addition to the DLL_PROCESS_ATTACH notification if I create a thread directly from DLL_PROCESS_ATTACH ?
EDIT: I've wrote a little test application that loads a library that spawns a thread:
#include <Windows.h>
#include <iostream>
using namespace std;
int main()
{
HMODULE hmLib = LoadLibraryA( "theDll.dll" );
HANDLE &hDllThread = *(HANDLE *)GetProcAddress( hmLib, "hDllThread" );
WaitForSingleObject( hDllThread, INFINITE );
cout << "thead terminated " << endl;
cout << "thread id: " << GetCurrentThreadId() << endl << endl;
}
Here's the DLL:
#include <Windows.h>
#include <iostream>
using namespace std;
extern "C"
__declspec(dllexport)
HANDLE hDllThread = NULL;
void printThreadId()
{
cout << "thread id: " << GetCurrentThreadId() << endl;
};
BOOL APIENTRY DllMain( HMODULE hModule, DWORD dwReason, LPVOID lpReserved )
{
switch( dwReason )
{
case DLL_PROCESS_ATTACH:
{
printThreadId();
cout << "process attach" << endl << endl;
::hDllThread = CreateThread( nullptr, 0,
[]( LPVOID ) -> DWORD
{
cout << "created thread id: " << GetCurrentThreadId() << endl;
cout << endl;
return 0;
}, nullptr, 0, nullptr );
// don't do that here
// WaitForSingleObject( ::hDllThread, INFINITE );
break;
}
case DLL_THREAD_ATTACH:
printThreadId();
cout << "thread attach" << endl << endl;
// don't do that here
// WaitForSingleObject( ::hDllThread, INFINITE );
break;
case DLL_THREAD_DETACH:
printThreadId();
cout << "thread detach" << endl << endl;
break;
case DLL_PROCESS_DETACH:
printThreadId();
cout << "process detach" << endl << endl;
break;
}
return TRUE;
}
static struct S
{
S()
{
printThreadId();
cout << "statics are initialized, but not thread locals" << endl << endl;
}
} s;
On my computer this prints:
thread id: 14692
statics are initialized, but not thread locals
thread id: 14692
process attach
thread id: 9396
thread attach
created thread id: 9396
thread id: 9396
thread detach
thead terminated
thread id: 14692
thread id: 14692
process detach
"thread attach" is printed before "created thread" in the context of the new thread. If I wait for the thread to terminate in DLL_PROCESS_ATTACH or DLL_THREAD_ATTACH I wait forever. So the entry point is called after both calls. Is this documented ?
CodePudding user response:
1.Do I have to call TlsAlloc() in DLL_PROCESS_ATTACH once genrally since the DLL hasn't any addional calls with DLL_THREAD_ATTACH for the thread doing the LoadLibrary() ?
Call TlsAlloc() won't do anything for your current question.
Each time the process creates a new thread, the entry-point function is called with the DLL_THREAD_ATTACH value.
2.So the entry point is called after both calls. Is this documented ?
Raymond Chen has explained thread creation and running process in his blog.
When you call CreateThread, a kernel thread object is created and scheduled. Once the thread gets a chance to run, the kernel calls all the DllMain functions with the DLL_THREAD_ATTACH code. Once that’s done, the thread’s entry point is called.
In MSDN, You can refer to this official document.
DLL_THREAD_ATTACH, Note that a DLL's entry-point function is called with this value only by threads created after the DLL is loaded by the process.
CodePudding user response:
Sorry, everything I told based on outdated informaton. Before Vista dynamially loaded DLLs with thread locals weren't reliable.
Everything is fine with thread_local / __declspec(thread) in DLLs for years.