[General] Fix a few memory leaks in threads
Destroying threads past when uninitializing the library is illegal
This commit is contained in:
parent
54323c2c0b
commit
80e88f1572
@ -3,6 +3,7 @@
|
|||||||
namespace Components
|
namespace Components
|
||||||
{
|
{
|
||||||
bool Loader::Pregame = true;
|
bool Loader::Pregame = true;
|
||||||
|
bool Loader::Postgame = false;
|
||||||
std::vector<Component*> Loader::Components;
|
std::vector<Component*> Loader::Components;
|
||||||
Utils::Memory::Allocator Loader::MemAllocator;
|
Utils::Memory::Allocator Loader::MemAllocator;
|
||||||
|
|
||||||
@ -14,6 +15,7 @@ namespace Components
|
|||||||
void Loader::Initialize()
|
void Loader::Initialize()
|
||||||
{
|
{
|
||||||
Loader::Pregame = true;
|
Loader::Pregame = true;
|
||||||
|
Loader::Postgame = false;
|
||||||
Loader::MemAllocator.clear();
|
Loader::MemAllocator.clear();
|
||||||
|
|
||||||
Loader::Register(new Flags());
|
Loader::Register(new Flags());
|
||||||
@ -86,6 +88,8 @@ namespace Components
|
|||||||
|
|
||||||
void Loader::Uninitialize()
|
void Loader::Uninitialize()
|
||||||
{
|
{
|
||||||
|
Loader::PreDestroy();
|
||||||
|
|
||||||
std::reverse(Loader::Components.begin(), Loader::Components.end());
|
std::reverse(Loader::Components.begin(), Loader::Components.end());
|
||||||
for (auto component : Loader::Components)
|
for (auto component : Loader::Components)
|
||||||
{
|
{
|
||||||
@ -102,6 +106,20 @@ namespace Components
|
|||||||
Loader::MemAllocator.clear();
|
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 Loader::PerformUnitTests()
|
||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
@ -12,6 +12,10 @@ namespace Components
|
|||||||
virtual const char* getName() { return "Unknown"; };
|
virtual const char* getName() { return "Unknown"; };
|
||||||
#endif
|
#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
|
virtual bool unitTest() { return true; }; // Unit testing entry
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -20,6 +24,7 @@ namespace Components
|
|||||||
public:
|
public:
|
||||||
static void Initialize();
|
static void Initialize();
|
||||||
static void Uninitialize();
|
static void Uninitialize();
|
||||||
|
static void PreDestroy();
|
||||||
static bool PerformUnitTests();
|
static bool PerformUnitTests();
|
||||||
static bool PerformingUnitTests();
|
static bool PerformingUnitTests();
|
||||||
static void Register(Component* component);
|
static void Register(Component* component);
|
||||||
@ -30,6 +35,7 @@ namespace Components
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static bool Pregame;
|
static bool Pregame;
|
||||||
|
static bool Postgame;
|
||||||
static std::vector<Component*> Components;
|
static std::vector<Component*> Components;
|
||||||
static Utils::Memory::Allocator MemAllocator;
|
static Utils::Memory::Allocator MemAllocator;
|
||||||
};
|
};
|
||||||
|
@ -438,6 +438,11 @@ namespace Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
Auth::~Auth()
|
Auth::~Auth()
|
||||||
|
{
|
||||||
|
Auth::StoreKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Auth::preDestroy()
|
||||||
{
|
{
|
||||||
Auth::TokenContainer.cancel = true;
|
Auth::TokenContainer.cancel = true;
|
||||||
Auth::TokenContainer.generating = false;
|
Auth::TokenContainer.generating = false;
|
||||||
@ -447,8 +452,6 @@ namespace Components
|
|||||||
{
|
{
|
||||||
Auth::TokenContainer.thread.join();
|
Auth::TokenContainer.thread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
Auth::StoreKey();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Auth::unitTest()
|
bool Auth::unitTest()
|
||||||
|
@ -12,6 +12,7 @@ namespace Components
|
|||||||
const char* getName() override { return "Auth"; };
|
const char* getName() override { return "Auth"; };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void preDestroy() override;
|
||||||
bool unitTest() override;
|
bool unitTest() override;
|
||||||
|
|
||||||
static void StoreKey();
|
static void StoreKey();
|
||||||
|
@ -98,6 +98,11 @@ namespace Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
Discovery::~Discovery()
|
Discovery::~Discovery()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Discovery::preDestroy()
|
||||||
{
|
{
|
||||||
Discovery::IsPerforming = false;
|
Discovery::IsPerforming = false;
|
||||||
Discovery::IsTerminating = true;
|
Discovery::IsTerminating = true;
|
||||||
|
@ -12,6 +12,8 @@ namespace Components
|
|||||||
const char* getName() override { return "Discovery"; };
|
const char* getName() override { return "Discovery"; };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void preDestroy() override;
|
||||||
|
|
||||||
static void Perform();
|
static void Perform();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -633,7 +633,11 @@ namespace Components
|
|||||||
{
|
{
|
||||||
mg_mgr_free(&Download::Mgr);
|
mg_mgr_free(&Download::Mgr);
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
|
||||||
|
void Download::preDestroy()
|
||||||
|
{
|
||||||
|
if (!Dedicated::IsEnabled())
|
||||||
{
|
{
|
||||||
Download::CLDownload.clear();
|
Download::CLDownload.clear();
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ namespace Components
|
|||||||
const char* getName() override { return "Download"; };
|
const char* getName() override { return "Download"; };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void preDestroy() override;
|
||||||
|
|
||||||
static void InitiateClientDownload(std::string mod);
|
static void InitiateClientDownload(std::string mod);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -234,4 +234,10 @@ namespace Components
|
|||||||
IPCPipe::Write("ping", "");
|
IPCPipe::Write("ping", "");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IPCPipe::preDestroy()
|
||||||
|
{
|
||||||
|
//IPCPipe::ServerPipe.destroy();
|
||||||
|
//IPCPipe::ClientPipe.destroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,8 @@ namespace Components
|
|||||||
void setCallback(std::string command, Utils::Slot<PacketCallback> callback);
|
void setCallback(std::string command, Utils::Slot<PacketCallback> callback);
|
||||||
void onConnect(Callback callback);
|
void onConnect(Callback callback);
|
||||||
|
|
||||||
|
void destroy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Utils::Slot<void()> connectCallback;
|
Utils::Slot<void()> connectCallback;
|
||||||
std::map<std::string, Utils::Slot<PacketCallback>> packetCallbacks;
|
std::map<std::string, Utils::Slot<PacketCallback>> packetCallbacks;
|
||||||
@ -53,7 +55,6 @@ namespace Components
|
|||||||
char pipeFile[MAX_PATH];
|
char pipeFile[MAX_PATH];
|
||||||
unsigned int reconnectAttempt;
|
unsigned int reconnectAttempt;
|
||||||
|
|
||||||
void destroy();
|
|
||||||
void setName(std::string name);
|
void setName(std::string name);
|
||||||
|
|
||||||
static void ReceiveThread(Pipe* pipe);
|
static void ReceiveThread(Pipe* pipe);
|
||||||
@ -68,6 +69,8 @@ namespace Components
|
|||||||
const char* getName() override { return "IPCPipe"; };
|
const char* getName() override { return "IPCPipe"; };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void preDestroy() override;
|
||||||
|
|
||||||
static bool Write(std::string command, std::string data);
|
static bool Write(std::string command, std::string data);
|
||||||
static void On(std::string command, Utils::Slot<Pipe::PacketCallback> callback);
|
static void On(std::string command, Utils::Slot<Pipe::PacketCallback> callback);
|
||||||
|
|
||||||
|
@ -190,6 +190,11 @@ namespace Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
News::~News()
|
News::~News()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void News::preDestroy()
|
||||||
{
|
{
|
||||||
News::Terminate = true;
|
News::Terminate = true;
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ namespace Components
|
|||||||
const char* getName() override { return "News"; };
|
const char* getName() override { return "News"; };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void preDestroy() override;
|
||||||
bool unitTest() override;
|
bool unitTest() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -174,6 +174,9 @@ namespace Components
|
|||||||
|
|
||||||
QuickPatch::QuickPatch()
|
QuickPatch::QuickPatch()
|
||||||
{
|
{
|
||||||
|
// Make sure preDestroy is called when the game shuts down
|
||||||
|
QuickPatch::OnShutdown(Loader::PreDestroy);
|
||||||
|
|
||||||
// protocol version (workaround for hacks)
|
// protocol version (workaround for hacks)
|
||||||
Utils::Hook::Set<int>(0x4FB501, PROTOCOL);
|
Utils::Hook::Set<int>(0x4FB501, PROTOCOL);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user