VideoConfig: Prevent race condition on g_Config when refreshing

There was a race condition between the video thread and the host thread,
if corrections need to be made by VerifyValidity(). Briefly, the config
will contain invalid values. Instead, pause emulation first, which will
flush the video thread, update the config and correct it, then resume
emulation, after which the video thread will detect the config has
changed and act accordingly.
This commit is contained in:
Stenzek 2017-10-10 23:52:17 +10:00
parent 1a4883ac5a
commit edb5f855c2
3 changed files with 10 additions and 3 deletions
Source/Core

@ -321,7 +321,10 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
wxGetTranslation(StrToWxStr(title)))), wxGetTranslation(StrToWxStr(title)))),
vconfig(g_Config) vconfig(g_Config)
{ {
vconfig.Refresh(); // We don't need to load the config if the core is running, since it would have been done
// at startup time already.
if (!Core::IsRunning())
vconfig.Refresh();
Bind(wxEVT_UPDATE_UI, &VideoConfigDiag::OnUpdateUI, this); Bind(wxEVT_UPDATE_UI, &VideoConfigDiag::OnUpdateUI, this);

@ -192,7 +192,6 @@ void VideoBackendBase::InitializeShared()
g_Config.Refresh(); g_Config.Refresh();
g_Config.UpdateProjectionHack(); g_Config.UpdateProjectionHack();
g_Config.VerifyValidity();
UpdateActiveConfig(); UpdateActiveConfig();
} }

@ -48,7 +48,12 @@ void VideoConfig::Refresh()
{ {
if (!s_has_registered_callback) if (!s_has_registered_callback)
{ {
Config::AddConfigChangedCallback([]() { g_Config.Refresh(); }); // There was a race condition between the video thread and the host thread here, if
// corrections need to be made by VerifyValidity(). Briefly, the config will contain
// invalid values. Instead, pause emulation first, which will flush the video thread,
// update the config and correct it, then resume emulation, after which the video
// thread will detect the config has changed and act accordingly.
Config::AddConfigChangedCallback([]() { Core::RunAsCPUThread([]() { g_Config.Refresh(); }); });
s_has_registered_callback = true; s_has_registered_callback = true;
} }