[General] Fix a few memory leaks in threads

Destroying threads past when uninitializing the library is illegal
This commit is contained in:
momo5502 2017-01-23 22:06:50 +01:00
parent 54323c2c0b
commit 80e88f1572
13 changed files with 63 additions and 4 deletions

View File

@ -3,6 +3,7 @@
namespace Components
{
bool Loader::Pregame = true;
bool Loader::Postgame = false;
std::vector<Component*> Loader::Components;
Utils::Memory::Allocator Loader::MemAllocator;
@ -14,6 +15,7 @@ namespace Components
void Loader::Initialize()
{
Loader::Pregame = true;
Loader::Postgame = false;
Loader::MemAllocator.clear();
Loader::Register(new Flags());
@ -86,6 +88,8 @@ namespace Components
void Loader::Uninitialize()
{
Loader::PreDestroy();
std::reverse(Loader::Components.begin(), Loader::Components.end());
for (auto component : Loader::Components)
{
@ -102,6 +106,20 @@ namespace Components
Loader::MemAllocator.clear();
}
void Loader::PreDestroy()
{
if(!Loader::Postgame)
{
Loader::Postgame = true;
std::reverse(Loader::Components.begin(), Loader::Components.end());
for (auto component : Loader::Components)
{
component->preDestroy();
}
}
}
bool Loader::PerformUnitTests()
{
bool result = true;

View File

@ -12,6 +12,10 @@ namespace Components
virtual const char* getName() { return "Unknown"; };
#endif
// It's illegal to spawn threads in DLLMain, and apparently it causes problems if they are destroyed there as well.
// This method is called before DLLMain (if possible) and should to destroy threads.
// It's not 100% guaranteed that it's called outside DLLMain, as it depends on the game, but it's 100% guaranteed, that it is called at all.
virtual void preDestroy() {};
virtual bool unitTest() { return true; }; // Unit testing entry
};
@ -20,6 +24,7 @@ namespace Components
public:
static void Initialize();
static void Uninitialize();
static void PreDestroy();
static bool PerformUnitTests();
static bool PerformingUnitTests();
static void Register(Component* component);
@ -30,6 +35,7 @@ namespace Components
private:
static bool Pregame;
static bool Postgame;
static std::vector<Component*> Components;
static Utils::Memory::Allocator MemAllocator;
};

View File

@ -438,6 +438,11 @@ namespace Components
}
Auth::~Auth()
{
Auth::StoreKey();
}
void Auth::preDestroy()
{
Auth::TokenContainer.cancel = true;
Auth::TokenContainer.generating = false;
@ -447,8 +452,6 @@ namespace Components
{
Auth::TokenContainer.thread.join();
}
Auth::StoreKey();
}
bool Auth::unitTest()

View File

@ -12,6 +12,7 @@ namespace Components
const char* getName() override { return "Auth"; };
#endif
void preDestroy() override;
bool unitTest() override;
static void StoreKey();

View File

@ -98,6 +98,11 @@ namespace Components
}
Discovery::~Discovery()
{
}
void Discovery::preDestroy()
{
Discovery::IsPerforming = false;
Discovery::IsTerminating = true;

View File

@ -12,6 +12,8 @@ namespace Components
const char* getName() override { return "Discovery"; };
#endif
void preDestroy() override;
static void Perform();
private:

View File

@ -633,7 +633,11 @@ namespace Components
{
mg_mgr_free(&Download::Mgr);
}
else
}
void Download::preDestroy()
{
if (!Dedicated::IsEnabled())
{
Download::CLDownload.clear();
}

View File

@ -12,6 +12,8 @@ namespace Components
const char* getName() override { return "Download"; };
#endif
void preDestroy() override;
static void InitiateClientDownload(std::string mod);
private:

View File

@ -234,4 +234,10 @@ namespace Components
IPCPipe::Write("ping", "");
});
}
void IPCPipe::preDestroy()
{
//IPCPipe::ServerPipe.destroy();
//IPCPipe::ClientPipe.destroy();
}
}

View File

@ -38,6 +38,8 @@ namespace Components
void setCallback(std::string command, Utils::Slot<PacketCallback> callback);
void onConnect(Callback callback);
void destroy();
private:
Utils::Slot<void()> connectCallback;
std::map<std::string, Utils::Slot<PacketCallback>> packetCallbacks;
@ -53,7 +55,6 @@ namespace Components
char pipeFile[MAX_PATH];
unsigned int reconnectAttempt;
void destroy();
void setName(std::string name);
static void ReceiveThread(Pipe* pipe);
@ -68,6 +69,8 @@ namespace Components
const char* getName() override { return "IPCPipe"; };
#endif
void preDestroy() override;
static bool Write(std::string command, std::string data);
static void On(std::string command, Utils::Slot<Pipe::PacketCallback> callback);

View File

@ -190,6 +190,11 @@ namespace Components
}
News::~News()
{
}
void News::preDestroy()
{
News::Terminate = true;

View File

@ -12,6 +12,7 @@ namespace Components
const char* getName() override { return "News"; };
#endif
void preDestroy() override;
bool unitTest() override;
private:

View File

@ -174,6 +174,9 @@ namespace Components
QuickPatch::QuickPatch()
{
// Make sure preDestroy is called when the game shuts down
QuickPatch::OnShutdown(Loader::PreDestroy);
// protocol version (workaround for hacks)
Utils::Hook::Set<int>(0x4FB501, PROTOCOL);