mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-18 14:08: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 <new>
|
||||
#include <stack>
|
||||
#include <tuple>
|
||||
|
||||
#include <base/hash.h>
|
||||
|
@ -4547,7 +4548,6 @@ int main(int argc, const char **argv)
|
|||
CCmdlineFix CmdlineFix(&argc, &argv);
|
||||
|
||||
bool Silent = false;
|
||||
bool RandInitFailed = false;
|
||||
|
||||
for(int i = 1; i < argc; i++)
|
||||
{
|
||||
|
@ -4582,17 +4582,42 @@ int main(int argc, const char **argv)
|
|||
vpLoggers.push_back(pFutureAssertionLogger);
|
||||
log_set_global_logger(log_logger_collection(std::move(vpLoggers)).release());
|
||||
|
||||
if(secure_random_init() != 0)
|
||||
{
|
||||
RandInitFailed = true;
|
||||
}
|
||||
std::stack<std::function<void()>> CleanerFunctions;
|
||||
std::function<void()> PerformCleanup = [&CleanerFunctions]() mutable {
|
||||
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();
|
||||
CleanerFunctions.push([]() { NotificationsUninit(); });
|
||||
|
||||
CClient *pClient = CreateClient();
|
||||
IKernel *pKernel = IKernel::Create();
|
||||
pKernel->RegisterInterface(pClient, false);
|
||||
pClient->RegisterInterfaces();
|
||||
CleanerFunctions.push([pKernel, pClient]() {
|
||||
pKernel->Shutdown();
|
||||
delete pKernel;
|
||||
pClient->~CClient();
|
||||
free(pClient);
|
||||
});
|
||||
|
||||
const std::thread::id MainThreadId = std::this_thread::get_id();
|
||||
dbg_assert_set_handler([MainThreadId, pClient](const char *pMsg) {
|
||||
|
@ -4604,6 +4629,7 @@ int main(int argc, const char **argv)
|
|||
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);
|
||||
pClient->ShowMessageBox("Assertion Error", aMessage);
|
||||
// Client will crash due to assertion, don't call PerformAllCleanup in this inconsistent state
|
||||
});
|
||||
|
||||
// create the components
|
||||
|
@ -4634,6 +4660,7 @@ int main(int argc, const char **argv)
|
|||
const char *pError = "Failed to initialize the secure RNG.";
|
||||
dbg_msg("secure", "%s", pError);
|
||||
pClient->ShowMessageBox("Secure RNG Error", pError);
|
||||
PerformAllCleanup();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -4668,9 +4695,7 @@ int main(int argc, const char **argv)
|
|||
const char *pError = "Failed to register an interface.";
|
||||
dbg_msg("client", "%s", pError);
|
||||
pClient->ShowMessageBox("Kernel Error", pError);
|
||||
delete pKernel;
|
||||
pClient->~CClient();
|
||||
free(pClient);
|
||||
PerformAllCleanup();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -4695,6 +4720,7 @@ int main(int argc, const char **argv)
|
|||
const char *pError = "Failed to load config from '" CONFIG_FILE "'.";
|
||||
dbg_msg("client", "%s", pError);
|
||||
pClient->ShowMessageBox("Config File Error", pError);
|
||||
PerformAllCleanup();
|
||||
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());
|
||||
dbg_msg("client", "%s", aError);
|
||||
pClient->ShowMessageBox("SDL Error", aError);
|
||||
PerformAllCleanup();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef CONF_PLATFORM_ANDROID
|
||||
atexit(SDL_Quit);
|
||||
#endif
|
||||
CleanerFunctions.push([]() { SDL_Quit(); });
|
||||
|
||||
// run the client
|
||||
dbg_msg("client", "starting...");
|
||||
|
@ -4781,23 +4805,14 @@ int main(int argc, const char **argv)
|
|||
pStorage->GetBinaryPath(PLAT_CLIENT_EXEC, aRestartBinaryPath, sizeof(aRestartBinaryPath));
|
||||
}
|
||||
|
||||
pClient->~CClient();
|
||||
free(pClient);
|
||||
pKernel->Shutdown();
|
||||
delete pKernel;
|
||||
SDL_Quit();
|
||||
NotificationsUninit();
|
||||
secure_random_uninit();
|
||||
PerformCleanup();
|
||||
|
||||
if(Restarting)
|
||||
{
|
||||
shell_execute(aRestartBinaryPath);
|
||||
}
|
||||
|
||||
#ifdef CONF_PLATFORM_ANDROID
|
||||
// properly close this native thread, so globals are destructed
|
||||
std::exit(0);
|
||||
#endif
|
||||
PerformFinalCleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue