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

View File

@ -321,7 +321,10 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
wxGetTranslation(StrToWxStr(title)))),
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);

View File

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

View File

@ -48,7 +48,12 @@ void VideoConfig::Refresh()
{
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;
}