-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Closed
Labels
enhancementSomething can be improvedSomething can be improvedwontfixThis will not be worked onThis will not be worked on
Description
I'm referring to this #448 (comment)
Adding a .TLS section to a DLL that previously didn't have one can push a program over the TLS slot limit, so it's a breaking change.
My understanding is the limit in Vista was changed from ~58 to ~1000ish but that there is still a limit.
I think that TLS algorithm starting from Vista allows virtually infinite TLS slots (that is limited only by virtual address space).
I think the algorithm abandons old TLS tables without deallocating them. They are deallocated on thread exit. TLS slot table just grows, but with ability of slot reuse. Something like this.
I'm not sure if it is true for Vista, but at least for Windows 10 it seems to work.
I can show, please follow me:
d:\Temp>type myshka.cpp
thread_local int i = 0;
extern "C" __declspec(dllexport) int* GetTlsVar()
{
i += 1;
return &i;
}
d:\Temp>type koshka.cpp
#include <Windows.h>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <unordered_set>
int main()
{
std::vector<HMODULE> dlls;
for (int i = 0; i < 30'000; i++)
{
std::ostringstream name;
std::ostringstream cmd;
name << "myshka_" << i <<".dll";
if (!::CopyFileA("myshka.dll", name.str().c_str(), FALSE))
{
std::cerr << "can't copy\n";
return 2;
}
HMODULE m = ::LoadLibraryA(name.str().c_str());
if (m == NULL)
{
std::cerr << "can't load\n";
return 3;
}
dlls.push_back(m);
}
std::cout << "dlls loaded\n";
for (int expectation : {1, 2})
{
std::unordered_set<int*> uniq;
for (HMODULE m : dlls)
{
auto TlsVarFcnPtr = reinterpret_cast<int*(*)()>(::GetProcAddress(m, "GetTlsVar"));
auto TlsVarPtr = TlsVarFcnPtr();
if (TlsVarPtr == NULL)
{
std::cerr << "can't indirect\n";
return 4;
}
auto TlsVarVal = *TlsVarPtr;
if (TlsVarVal != expectation || uniq.count(TlsVarPtr) != 0)
{
std::cerr << "Bad TLS data " << TlsVarPtr << '\t' << TlsVarVal << '\n';
return 5;
}
uniq.insert(TlsVarPtr);
}
}
std::cout << "all fine\n";
return 0;
}
d:\Temp>"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64
d:\Temp>cl /MD /EHsc myshka.cpp /link /DLL /out:myshka.dll
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
myshka.cpp
Microsoft (R) Incremental Linker Version 14.00.24215.1
Copyright (C) Microsoft Corporation. All rights reserved.
/out:myshka.exe
/DLL
/out:myshka.dll
myshka.obj
Creating library myshka.lib and object myshka.exp
d:\Temp>cl /MD /EHsc koshka.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
koshka.cpp
Microsoft (R) Incremental Linker Version 14.00.24215.1
Copyright (C) Microsoft Corporation. All rights reserved.
/out:koshka.exe
koshka.obj
d:\Temp>koshka
dlls loaded
all fine
Metadata
Metadata
Assignees
Labels
enhancementSomething can be improvedSomething can be improvedwontfixThis will not be worked onThis will not be worked on