mirror of
https://github.com/ddnet/ddnet.git
synced 2024-09-20 09:34:19 +00:00
Properly uninitialize all client components
Track stack of cleaner functions that destruct client components so exactly the correct cleanup is performed in the reverse order of initialization. This allows performing the cleanup also in the early-return cases without introducing duplicate code.
This commit is contained in:
parent
95b0f8c1e4
commit
c8b69dd815
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include <stack>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#include <base/hash.h>
|
#include <base/hash.h>
|
||||||
|
@ -4547,7 +4548,6 @@ int main(int argc, const char **argv)
|
||||||
CCmdlineFix CmdlineFix(&argc, &argv);
|
CCmdlineFix CmdlineFix(&argc, &argv);
|
||||||
|
|
||||||
bool Silent = false;
|
bool Silent = false;
|
||||||
bool RandInitFailed = false;
|
|
||||||
|
|
||||||
for(int i = 1; i < argc; i++)
|
for(int i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
|
@ -4582,17 +4582,42 @@ int main(int argc, const char **argv)
|
||||||
vpLoggers.push_back(pFutureAssertionLogger);
|
vpLoggers.push_back(pFutureAssertionLogger);
|
||||||
log_set_global_logger(log_logger_collection(std::move(vpLoggers)).release());
|
log_set_global_logger(log_logger_collection(std::move(vpLoggers)).release());
|
||||||
|
|
||||||
if(secure_random_init() != 0)
|
std::stack<std::function<void()>> CleanerFunctions;
|
||||||
{
|
std::function<void()> PerformCleanup = [&CleanerFunctions]() mutable {
|
||||||
RandInitFailed = true;
|
while(!CleanerFunctions.empty())
|
||||||
}
|
{
|
||||||
|
CleanerFunctions.top()();
|
||||||
|
CleanerFunctions.pop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::function<void()> PerformFinalCleanup = []() {
|
||||||
|
#ifdef CONF_PLATFORM_ANDROID
|
||||||
|
// properly close this native thread, so globals are destructed
|
||||||
|
std::exit(0);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
std::function<void()> PerformAllCleanup = [PerformCleanup, PerformFinalCleanup]() mutable {
|
||||||
|
PerformCleanup();
|
||||||
|
PerformFinalCleanup();
|
||||||
|
};
|
||||||
|
|
||||||
|
const bool RandInitFailed = secure_random_init() != 0;
|
||||||
|
if(!RandInitFailed)
|
||||||
|
CleanerFunctions.push([]() { secure_random_uninit(); });
|
||||||
|
|
||||||
NotificationsInit();
|
NotificationsInit();
|
||||||
|
CleanerFunctions.push([]() { NotificationsUninit(); });
|
||||||
|
|
||||||
CClient *pClient = CreateClient();
|
CClient *pClient = CreateClient();
|
||||||
IKernel *pKernel = IKernel::Create();
|
IKernel *pKernel = IKernel::Create();
|
||||||
pKernel->RegisterInterface(pClient, false);
|
pKernel->RegisterInterface(pClient, false);
|
||||||
pClient->RegisterInterfaces();
|
pClient->RegisterInterfaces();
|
||||||
|
CleanerFunctions.push([pKernel, pClient]() {
|
||||||
|
pKernel->Shutdown();
|
||||||
|
delete pKernel;
|
||||||
|
pClient->~CClient();
|
||||||
|
free(pClient);
|
||||||
|
});
|
||||||
|
|
||||||
const std::thread::id MainThreadId = std::this_thread::get_id();
|
const std::thread::id MainThreadId = std::this_thread::get_id();
|
||||||
dbg_assert_set_handler([MainThreadId, pClient](const char *pMsg) {
|
dbg_assert_set_handler([MainThreadId, pClient](const char *pMsg) {
|
||||||
|
@ -4604,6 +4629,7 @@ int main(int argc, const char **argv)
|
||||||
char aMessage[512];
|
char aMessage[512];
|
||||||
str_format(aMessage, sizeof(aMessage), "An assertion error occured. Please write down or take a screenshot of the following information and report this error.\nPlease also share the assert log which you should find in the 'dumps' folder in your config directory.\n\n%s\n\nPlatform: %s\nGame version: %s %s\nOS version: %s", pMsg, CONF_PLATFORM_STRING, GAME_RELEASE_VERSION, GIT_SHORTREV_HASH != nullptr ? GIT_SHORTREV_HASH : "", aVersionStr);
|
str_format(aMessage, sizeof(aMessage), "An assertion error occured. Please write down or take a screenshot of the following information and report this error.\nPlease also share the assert log which you should find in the 'dumps' folder in your config directory.\n\n%s\n\nPlatform: %s\nGame version: %s %s\nOS version: %s", pMsg, CONF_PLATFORM_STRING, GAME_RELEASE_VERSION, GIT_SHORTREV_HASH != nullptr ? GIT_SHORTREV_HASH : "", aVersionStr);
|
||||||
pClient->ShowMessageBox("Assertion Error", aMessage);
|
pClient->ShowMessageBox("Assertion Error", aMessage);
|
||||||
|
// Client will crash due to assertion, don't call PerformAllCleanup in this inconsistent state
|
||||||
});
|
});
|
||||||
|
|
||||||
// create the components
|
// create the components
|
||||||
|
@ -4634,6 +4660,7 @@ int main(int argc, const char **argv)
|
||||||
const char *pError = "Failed to initialize the secure RNG.";
|
const char *pError = "Failed to initialize the secure RNG.";
|
||||||
dbg_msg("secure", "%s", pError);
|
dbg_msg("secure", "%s", pError);
|
||||||
pClient->ShowMessageBox("Secure RNG Error", pError);
|
pClient->ShowMessageBox("Secure RNG Error", pError);
|
||||||
|
PerformAllCleanup();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4668,9 +4695,7 @@ int main(int argc, const char **argv)
|
||||||
const char *pError = "Failed to register an interface.";
|
const char *pError = "Failed to register an interface.";
|
||||||
dbg_msg("client", "%s", pError);
|
dbg_msg("client", "%s", pError);
|
||||||
pClient->ShowMessageBox("Kernel Error", pError);
|
pClient->ShowMessageBox("Kernel Error", pError);
|
||||||
delete pKernel;
|
PerformAllCleanup();
|
||||||
pClient->~CClient();
|
|
||||||
free(pClient);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4695,6 +4720,7 @@ int main(int argc, const char **argv)
|
||||||
const char *pError = "Failed to load config from '" CONFIG_FILE "'.";
|
const char *pError = "Failed to load config from '" CONFIG_FILE "'.";
|
||||||
dbg_msg("client", "%s", pError);
|
dbg_msg("client", "%s", pError);
|
||||||
pClient->ShowMessageBox("Config File Error", pError);
|
pClient->ShowMessageBox("Config File Error", pError);
|
||||||
|
PerformAllCleanup();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4763,12 +4789,10 @@ int main(int argc, const char **argv)
|
||||||
str_format(aError, sizeof(aError), "Unable to initialize SDL base: %s", SDL_GetError());
|
str_format(aError, sizeof(aError), "Unable to initialize SDL base: %s", SDL_GetError());
|
||||||
dbg_msg("client", "%s", aError);
|
dbg_msg("client", "%s", aError);
|
||||||
pClient->ShowMessageBox("SDL Error", aError);
|
pClient->ShowMessageBox("SDL Error", aError);
|
||||||
|
PerformAllCleanup();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
CleanerFunctions.push([]() { SDL_Quit(); });
|
||||||
#ifndef CONF_PLATFORM_ANDROID
|
|
||||||
atexit(SDL_Quit);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// run the client
|
// run the client
|
||||||
dbg_msg("client", "starting...");
|
dbg_msg("client", "starting...");
|
||||||
|
@ -4781,23 +4805,14 @@ int main(int argc, const char **argv)
|
||||||
pStorage->GetBinaryPath(PLAT_CLIENT_EXEC, aRestartBinaryPath, sizeof(aRestartBinaryPath));
|
pStorage->GetBinaryPath(PLAT_CLIENT_EXEC, aRestartBinaryPath, sizeof(aRestartBinaryPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
pClient->~CClient();
|
PerformCleanup();
|
||||||
free(pClient);
|
|
||||||
pKernel->Shutdown();
|
|
||||||
delete pKernel;
|
|
||||||
SDL_Quit();
|
|
||||||
NotificationsUninit();
|
|
||||||
secure_random_uninit();
|
|
||||||
|
|
||||||
if(Restarting)
|
if(Restarting)
|
||||||
{
|
{
|
||||||
shell_execute(aRestartBinaryPath);
|
shell_execute(aRestartBinaryPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONF_PLATFORM_ANDROID
|
PerformFinalCleanup();
|
||||||
// properly close this native thread, so globals are destructed
|
|
||||||
std::exit(0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue