achievements: crash when unloading a game with active async task
Async tasks may reference the active game and will crash if it's been unloaded/freed. Fixes MINIDUMP-38H
This commit is contained in:
parent
4cd6278104
commit
8adec3f20b
|
@ -75,6 +75,8 @@ private:
|
||||||
std::pair<std::string, bool> getCachedImage(const char *url);
|
std::pair<std::string, bool> getCachedImage(const char *url);
|
||||||
void diskChange();
|
void diskChange();
|
||||||
void asyncTask(std::function<void()> f);
|
void asyncTask(std::function<void()> f);
|
||||||
|
void startThread();
|
||||||
|
void stopThread();
|
||||||
void backgroundThread();
|
void backgroundThread();
|
||||||
|
|
||||||
static void clientLoginWithTokenCallback(int result, const char *error_message, rc_client_t *client, void *userdata);
|
static void clientLoginWithTokenCallback(int result, const char *error_message, rc_client_t *client, void *userdata);
|
||||||
|
@ -195,6 +197,20 @@ void Achievements::asyncTask(std::function<void()> f)
|
||||||
resetEvent.Set();
|
resetEvent.Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Achievements::startThread()
|
||||||
|
{
|
||||||
|
threadRunning = true;
|
||||||
|
taskThread = std::thread(&Achievements::backgroundThread, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Achievements::stopThread()
|
||||||
|
{
|
||||||
|
threadRunning = false;
|
||||||
|
resetEvent.Set();
|
||||||
|
if (taskThread.joinable())
|
||||||
|
taskThread.join();
|
||||||
|
}
|
||||||
|
|
||||||
void Achievements::backgroundThread()
|
void Achievements::backgroundThread()
|
||||||
{
|
{
|
||||||
ThreadName _("RA-background");
|
ThreadName _("RA-background");
|
||||||
|
@ -227,8 +243,7 @@ bool Achievements::init()
|
||||||
//rc_client_set_unofficial_enabled(rc_client, 0);
|
//rc_client_set_unofficial_enabled(rc_client, 0);
|
||||||
//rc_client_set_spectator_mode_enabled(rc_client, 0);
|
//rc_client_set_spectator_mode_enabled(rc_client, 0);
|
||||||
loadCache();
|
loadCache();
|
||||||
threadRunning = true;
|
startThread();
|
||||||
taskThread = std::thread(&Achievements::backgroundThread, this);
|
|
||||||
|
|
||||||
if (!config::AchievementsUserName.get().empty() && !config::AchievementsToken.get().empty())
|
if (!config::AchievementsUserName.get().empty() && !config::AchievementsToken.get().empty())
|
||||||
{
|
{
|
||||||
|
@ -342,10 +357,7 @@ void Achievements::term()
|
||||||
if (rc_client == nullptr)
|
if (rc_client == nullptr)
|
||||||
return;
|
return;
|
||||||
unloadGame();
|
unloadGame();
|
||||||
threadRunning = false;
|
stopThread();
|
||||||
resetEvent.Set();
|
|
||||||
if (taskThread.joinable())
|
|
||||||
taskThread.join();
|
|
||||||
rc_client_destroy(rc_client);
|
rc_client_destroy(rc_client);
|
||||||
rc_client = nullptr;
|
rc_client = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -932,6 +944,9 @@ void Achievements::unloadGame()
|
||||||
active = false;
|
active = false;
|
||||||
paused = false;
|
paused = false;
|
||||||
EventManager::unlisten(Event::VBlank, emuEventCallback, this);
|
EventManager::unlisten(Event::VBlank, emuEventCallback, this);
|
||||||
|
// wait for all async tasks before unloading the game
|
||||||
|
stopThread();
|
||||||
|
startThread();
|
||||||
rc_client_unload_game(rc_client);
|
rc_client_unload_game(rc_client);
|
||||||
settings.raHardcoreMode = false;
|
settings.raHardcoreMode = false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue