[General] Fix protobuf and other memory leaks

This commit is contained in:
momo5502 2017-01-22 20:12:36 +01:00
parent f81a36ae3b
commit 2de95b4a3b
13 changed files with 119 additions and 55 deletions

View File

@ -4,6 +4,7 @@ namespace Components
{ {
bool Loader::Pregame = true; bool Loader::Pregame = true;
std::vector<Component*> Loader::Components; std::vector<Component*> Loader::Components;
Utils::Memory::Allocator Loader::MemAllocator;
bool Loader::IsPregame() bool Loader::IsPregame()
{ {
@ -13,6 +14,7 @@ namespace Components
void Loader::Initialize() void Loader::Initialize()
{ {
Loader::Pregame = true; Loader::Pregame = true;
Loader::MemAllocator.clear();
Loader::Register(new Flags()); Loader::Register(new Flags());
Loader::Register(new Singleton()); Loader::Register(new Singleton());
@ -97,6 +99,7 @@ namespace Components
} }
Loader::Components.clear(); Loader::Components.clear();
Loader::MemAllocator.clear();
} }
bool Loader::PerformUnitTests() bool Loader::PerformUnitTests()
@ -142,4 +145,9 @@ namespace Components
Loader::Components.push_back(component); Loader::Components.push_back(component);
} }
} }
Utils::Memory::Allocator* Loader::GetAlloctor()
{
return &Loader::MemAllocator;
}
} }

View File

@ -26,9 +26,12 @@ namespace Components
static bool IsPregame(); static bool IsPregame();
static Utils::Memory::Allocator* GetAlloctor();
private: private:
static bool Pregame; static bool Pregame;
static std::vector<Component*> Components; static std::vector<Component*> Components;
static Utils::Memory::Allocator MemAllocator;
}; };
} }

View File

@ -250,6 +250,7 @@ namespace Components
delwin(Console::InputWindow); delwin(Console::InputWindow);
delwin(Console::InfoWindow); delwin(Console::InfoWindow);
endwin(); endwin();
delscreen(SP);
Console::OutputWindow = nullptr; Console::OutputWindow = nullptr;
Console::InputWindow = nullptr; Console::InputWindow = nullptr;

View File

@ -289,6 +289,9 @@ namespace Components
if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) // Run zonebuilder as dedi :P if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) // Run zonebuilder as dedi :P
{ {
// Make sure all callbacks are handled
Dedicated::OnFrame(Steam::SteamAPI_RunCallbacks);
Dvar::Register<bool>("sv_lanOnly", false, Game::dvar_flag::DVAR_FLAG_NONE, "Don't act as node"); Dvar::Register<bool>("sv_lanOnly", false, Game::dvar_flag::DVAR_FLAG_NONE, "Don't act as node");
Utils::Hook(0x60BE98, Dedicated::InitDedicatedServer, HOOK_CALL).install()->quick(); Utils::Hook(0x60BE98, Dedicated::InitDedicatedServer, HOOK_CALL).install()->quick();

View File

@ -23,26 +23,28 @@ namespace Components
Discovery::IsTerminating = false; Discovery::IsTerminating = false;
Discovery::Thread = std::thread([] () Discovery::Thread = std::thread([] ()
{ {
while (!Discovery::IsTerminating)
{ {
if (Discovery::IsPerforming) while (!Discovery::IsTerminating)
{ {
int start = Game::Sys_Milliseconds(); if (Discovery::IsPerforming)
{
int start = Game::Sys_Milliseconds();
Logger::Print("Starting local server discovery...\n"); Logger::Print("Starting local server discovery...\n");
Discovery::Challenge = Utils::Cryptography::Rand::GenerateChallenge(); Discovery::Challenge = Utils::Cryptography::Rand::GenerateChallenge();
unsigned int minPort = Dvar::Var("net_discoveryPortRangeMin").get<unsigned int>(); unsigned int minPort = Dvar::Var("net_discoveryPortRangeMin").get<unsigned int>();
unsigned int maxPort = Dvar::Var("net_discoveryPortRangeMax").get<unsigned int>(); unsigned int maxPort = Dvar::Var("net_discoveryPortRangeMax").get<unsigned int>();
Network::BroadcastRange(minPort, maxPort, Utils::String::VA("discovery %s", Discovery::Challenge.data())); Network::BroadcastRange(minPort, maxPort, Utils::String::VA("discovery %s", Discovery::Challenge.data()));
Logger::Print("Discovery sent within %dms, awaiting responses...\n", Game::Sys_Milliseconds() - start); Logger::Print("Discovery sent within %dms, awaiting responses...\n", Game::Sys_Milliseconds() - start);
Discovery::IsPerforming = false; Discovery::IsPerforming = false;
}
std::this_thread::sleep_for(50ms);
} }
std::this_thread::sleep_for(50ms);
} }
}); });
@ -104,5 +106,7 @@ namespace Components
{ {
Discovery::Thread.join(); Discovery::Thread.join();
} }
Discovery::Thread = std::thread();
} }
} }

View File

@ -125,6 +125,8 @@ namespace Components
Logger::Print("Pipe thread terminated.\n"); Logger::Print("Pipe thread terminated.\n");
} }
this->thread = std::thread();
} }
void Pipe::setName(std::string name) void Pipe::setName(std::string name)
@ -138,40 +140,42 @@ namespace Components
void Pipe::ReceiveThread(Pipe* pipe) void Pipe::ReceiveThread(Pipe* pipe)
{ {
if (!pipe || pipe->type != IPCTYPE_SERVER || pipe->pipe == INVALID_HANDLE_VALUE || !pipe->pipe) return;
if (ConnectNamedPipe(pipe->pipe, nullptr) == FALSE)
{ {
Logger::Print("Failed to initialize pipe reading.\n"); if (!pipe || pipe->type != IPCTYPE_SERVER || pipe->pipe == INVALID_HANDLE_VALUE || !pipe->pipe) return;
return;
}
Logger::Print("Client connected to the pipe\n"); if (ConnectNamedPipe(pipe->pipe, nullptr) == FALSE)
pipe->connectCallback();
DWORD cbBytes;
while (pipe->threadAttached && pipe->pipe && pipe->pipe != INVALID_HANDLE_VALUE)
{
BOOL bResult = ReadFile(pipe->pipe, &pipe->packet, sizeof(pipe->packet), &cbBytes, nullptr);
if (bResult && cbBytes)
{ {
if (pipe->packetCallbacks.find(pipe->packet.command) != pipe->packetCallbacks.end()) Logger::Print("Failed to initialize pipe reading.\n");
return;
}
Logger::Print("Client connected to the pipe\n");
pipe->connectCallback();
DWORD cbBytes;
while (pipe->threadAttached && pipe->pipe && pipe->pipe != INVALID_HANDLE_VALUE)
{
BOOL bResult = ReadFile(pipe->pipe, &pipe->packet, sizeof(pipe->packet), &cbBytes, nullptr);
if (bResult && cbBytes)
{ {
pipe->packetCallbacks[pipe->packet.command](pipe->packet.buffer); if (pipe->packetCallbacks.find(pipe->packet.command) != pipe->packetCallbacks.end())
{
pipe->packetCallbacks[pipe->packet.command](pipe->packet.buffer);
}
} }
} else if (pipe->threadAttached && pipe->pipe != INVALID_HANDLE_VALUE)
else if (pipe->threadAttached && pipe->pipe != INVALID_HANDLE_VALUE) {
{ Logger::Print("Failed to read from client through pipe\n");
Logger::Print("Failed to read from client through pipe\n");
DisconnectNamedPipe(pipe->pipe); DisconnectNamedPipe(pipe->pipe);
ConnectNamedPipe(pipe->pipe, nullptr); ConnectNamedPipe(pipe->pipe, nullptr);
pipe->connectCallback(); pipe->connectCallback();
} }
ZeroMemory(&pipe->packet, sizeof(pipe->packet)); ZeroMemory(&pipe->packet, sizeof(pipe->packet));
}
} }
} }

View File

@ -161,25 +161,27 @@ namespace Components
News::Terminate = false; News::Terminate = false;
News::Thread = std::thread([] () News::Thread = std::thread([] ()
{ {
Localization::Set("MPUI_CHANGELOG_TEXT", Utils::Cache::GetFile("/iw4/changelog.txt"));
std::string data = Utils::Cache::GetFile("/iw4/motd.txt");
if (!data.empty())
{ {
Localization::Set("MPUI_MOTD_TEXT", data); Localization::Set("MPUI_CHANGELOG_TEXT", Utils::Cache::GetFile("/iw4/changelog.txt"));
}
if (!Loader::PerformingUnitTests()) std::string data = Utils::Cache::GetFile("/iw4/motd.txt");
{
while (!News::Terminate) if (!data.empty())
{ {
News::CheckForUpdate(); Localization::Set("MPUI_MOTD_TEXT", data);
}
// Sleep for 3 minutes if (!Loader::PerformingUnitTests())
for (int i = 0; i < 180 && !News::Terminate; ++i) {
while (!News::Terminate)
{ {
std::this_thread::sleep_for(1s); News::CheckForUpdate();
// Sleep for 3 minutes
for (int i = 0; i < 180 && !News::Terminate; ++i)
{
std::this_thread::sleep_for(1s);
}
} }
} }
} }
@ -195,5 +197,7 @@ namespace Components
{ {
News::Thread.join(); News::Thread.join();
} }
News::Thread = std::thread();
} }
} }

View File

@ -335,7 +335,7 @@ namespace Game
XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize) XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize)
{ {
int elSize = DB_GetXAssetSizeHandlers[type](); int elSize = DB_GetXAssetSizeHandlers[type]();
XAssetHeader poolEntry = { Utils::Memory::Allocate(newSize * elSize) }; XAssetHeader poolEntry = { Components::Loader::GetAlloctor()->allocate(newSize * elSize) };
DB_XAssetPool[type] = poolEntry; DB_XAssetPool[type] = poolEntry;
g_poolSize[type] = newSize; g_poolSize[type] = newSize;
return poolEntry; return poolEntry;

View File

@ -42,6 +42,8 @@ namespace Main
void Uninitialize() void Uninitialize()
{ {
Components::Loader::Uninitialize(); Components::Loader::Uninitialize();
Utils::Cache::Uninitialize();
google::protobuf::ShutdownProtobufLibrary();
} }
} }

View File

@ -7,26 +7,32 @@ namespace Steam
std::map<uint64_t, Callbacks::Base*> Callbacks::ResultHandlers; std::map<uint64_t, Callbacks::Base*> Callbacks::ResultHandlers;
std::vector<Callbacks::Result> Callbacks::Results; std::vector<Callbacks::Result> Callbacks::Results;
std::vector<Callbacks::Base*> Callbacks::CallbackList; std::vector<Callbacks::Base*> Callbacks::CallbackList;
std::recursive_mutex Callbacks::Mutex;
uint64_t Callbacks::RegisterCall() uint64_t Callbacks::RegisterCall()
{ {
std::lock_guard<std::recursive_mutex> _(Callbacks::Mutex);
Callbacks::Calls[++Callbacks::CallID] = false; Callbacks::Calls[++Callbacks::CallID] = false;
return Callbacks::CallID; return Callbacks::CallID;
} }
void Callbacks::RegisterCallback(Callbacks::Base* handler, int callback) void Callbacks::RegisterCallback(Callbacks::Base* handler, int callback)
{ {
std::lock_guard<std::recursive_mutex> _(Callbacks::Mutex);
handler->SetICallback(callback); handler->SetICallback(callback);
Callbacks::CallbackList.push_back(handler); Callbacks::CallbackList.push_back(handler);
} }
void Callbacks::RegisterCallResult(uint64_t call, Callbacks::Base* result) void Callbacks::RegisterCallResult(uint64_t call, Callbacks::Base* result)
{ {
std::lock_guard<std::recursive_mutex> _(Callbacks::Mutex);
Callbacks::ResultHandlers[call] = result; Callbacks::ResultHandlers[call] = result;
} }
void Callbacks::ReturnCall(void* data, int size, int type, uint64_t call) void Callbacks::ReturnCall(void* data, int size, int type, uint64_t call)
{ {
std::lock_guard<std::recursive_mutex> _(Callbacks::Mutex);
Callbacks::Result result; Callbacks::Result result;
Callbacks::Calls[call] = true; Callbacks::Calls[call] = true;
@ -41,7 +47,12 @@ namespace Steam
void Callbacks::RunCallbacks() void Callbacks::RunCallbacks()
{ {
for (auto result : Callbacks::Results) std::lock_guard<std::recursive_mutex> _(Callbacks::Mutex);
auto results = Callbacks::Results;
Callbacks::Results.clear();
for (auto result : results)
{ {
if (Callbacks::ResultHandlers.find(result.call) != Callbacks::ResultHandlers.end()) if (Callbacks::ResultHandlers.find(result.call) != Callbacks::ResultHandlers.end())
{ {
@ -61,6 +72,19 @@ namespace Steam
::Utils::Memory::Free(result.data); ::Utils::Memory::Free(result.data);
} }
} }
}
void Callbacks::Uninitialize()
{
std::lock_guard<std::recursive_mutex> _(Callbacks::Mutex);
for (auto result : Callbacks::Results)
{
if (result.data)
{
::Utils::Memory::Free(result.data);
}
}
Callbacks::Results.clear(); Callbacks::Results.clear();
} }
@ -111,6 +135,7 @@ namespace Steam
void SteamAPI_Shutdown() void SteamAPI_Shutdown()
{ {
Proxy::Uninititalize(); Proxy::Uninititalize();
Callbacks::Uninitialize();
} }
void SteamAPI_UnregisterCallResult() void SteamAPI_UnregisterCallResult()

View File

@ -81,12 +81,15 @@ namespace Steam
static void ReturnCall(void* data, int size, int type, uint64_t call); static void ReturnCall(void* data, int size, int type, uint64_t call);
static void RunCallbacks(); static void RunCallbacks();
static void Uninitialize();
private: private:
static uint64_t CallID; static uint64_t CallID;
static std::map<uint64_t, bool> Calls; static std::map<uint64_t, bool> Calls;
static std::map<uint64_t, Base*> ResultHandlers; static std::map<uint64_t, Base*> ResultHandlers;
static std::vector<Result> Results; static std::vector<Result> Results;
static std::vector<Base*> CallbackList; static std::vector<Base*> CallbackList;
static std::recursive_mutex Mutex;
}; };
STEAM_EXPORT bool SteamAPI_Init(); STEAM_EXPORT bool SteamAPI_Init();

View File

@ -47,4 +47,10 @@ namespace Utils
return Utils::WebIO(useragent, Cache::GetUrl(Cache::ValidUrl, path)).setTimeout(timeout)->get(); return Utils::WebIO(useragent, Cache::GetUrl(Cache::ValidUrl, path)).setTimeout(timeout)->get();
} }
} }
void Cache::Uninitialize()
{
std::lock_guard<std::mutex> _(Cache::CacheMutex);
Cache::ValidUrl.clear();
}
} }

View File

@ -7,6 +7,7 @@ namespace Utils
public: public:
static std::string GetStaticUrl(std::string path); static std::string GetStaticUrl(std::string path);
static std::string GetFile(std::string path, int timeout = 5000, std::string useragent = "IW4x"); static std::string GetFile(std::string path, int timeout = 5000, std::string useragent = "IW4x");
static void Uninitialize();
private: private:
static std::mutex CacheMutex; static std::mutex CacheMutex;