MemoryModulePP icon indicating copy to clipboard operation
MemoryModulePP copied to clipboard

C++11 thread_local

Open BadaPZ opened this issue 3 years ago • 8 comments

Hi, I integrated this great library into our application and we got an error when this application creates a C++11 thread. The callstack starts from last line of MmpUserThreadStart() and ends a thread_local variable reference. The variable is a simple pointer to a structure what is newed before the first usage of the pointer. The program did not use the MMPP api at this early stage just want to create some background threads. Without linking MMPP, no issue w the thread creation. Does the lib MMPP support C++11 thread_local?

BadaPZ avatar Feb 23 '22 15:02 BadaPZ

Sorry I can't reproduce this problem. The thread_local variable works correctly on my simple test program. Can you provide a code snippet that causes this problem?

bb107 avatar Feb 24 '22 00:02 bb107

I integrated MMPP into a larger build, cannot provide a small repro now. There is a.EXE it uses import lib to a b.DLL what links MMPP as a static lib. MMPP lib built crt Debug DLL, /EHa x64. b.DLL (crt debug dll, /EHa, x64) has a thread_local struct WorkData. In the init section inside b.DLL there is a new std::stread(threadWork,...) At the very beginning of the threadWork(), the thread wants to access WorkData but crashes with access violation at 0x0000000000000330 There are 2 treads created before MMPP registers itself, that threads can access WorkData without crashing. After the registration, the first new std::thread has this issue. VS2019

BadaPZ avatar Feb 24 '22 07:02 BadaPZ

Please answer these questions to help me build the test program:

  1. Is MMPP linked to a.EXE or b.DLL?
  2. When is WorkData initialized?
  3. Is WorkData a structure or a pointer to a structure?
  4. Is threadWork created by a.EXE or b.DLL?

bb107 avatar Feb 24 '22 08:02 bb107

  1. MMPP linked to the b.DLL. 2.-3. WorkData is a thread_local struct: thread_local RMTLSDATA g_WorkData; It is automatically initialized in every thread at the 1st reference to it by the CRT (I guess)

b.dll!RMTLSDATA::RMTLSDATA() Line 84 C++ b.dll!`dynamic initializer for 'g_WorkData''() Line 188 C++ [External Code]

  1. threadWork created by b.DLL

BadaPZ avatar Feb 24 '22 09:02 BadaPZ

If MMPP is statically linked, how did you create the threadWork thread before initializing MMPP and make it run?

bb107 avatar Feb 25 '22 01:02 bb107

in the b.DLL:

initbDll() { pThreadData = new THREAD_DATA; . . hthreadWork = new std::thread(threadWork, pThreadData); . }

static unsigned __stdcall threadWork(void *lpParam) { // read access violation 0x0000000000000215 <-- always a small number int a = g_WorkData.a; }

// if I do not link MMPP.lib to the b.DLL everything works. // the program calls MMPP api first time later

BadaPZ avatar Feb 25 '22 05:02 BadaPZ

When MMPP is not initialized, in the 1st worker thread: 00007FF91708A510 push rdi
00007FF91708A512 sub rsp,40h
if (g_pWorkData == NULL) 00007FF91708A516 mov eax,110h
00007FF91708A51B mov eax,eax
00007FF91708A51D mov ecx,dword ptr [_tls_index (07FF9173357C0h)] <--- tls index looks good 00007FF91708A523 mov rdx,qword ptr gs:[58h] <---- rdx looks real address 00007FF91708A52C mov rcx,qword ptr [rdx+rcx*8]
00007FF91708A530 cmp qword ptr [rax+rcx],0
00007FF91708A535 jne GetRmTLSData+85h (07FF91708A595h)

later, MMPP initialized next new thread(worker 2nd thread) --> and at same code, rdx 0

BadaPZ avatar Feb 25 '22 10:02 BadaPZ

Hi! Could you reproduce the issue?

BadaPZ avatar Mar 01 '22 09:03 BadaPZ