From edb5f855c28013e2782132251abd94bf1d040c13 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Tue, 10 Oct 2017 23:52:17 +1000 Subject: [PATCH] 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. --- Source/Core/DolphinWX/VideoConfigDiag.cpp | 5 ++++- Source/Core/VideoCommon/MainBase.cpp | 1 - Source/Core/VideoCommon/VideoConfig.cpp | 7 ++++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index 2718adb90e..08d2697514 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -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); diff --git a/Source/Core/VideoCommon/MainBase.cpp b/Source/Core/VideoCommon/MainBase.cpp index 5f5ce785ef..179efdbd41 100644 --- a/Source/Core/VideoCommon/MainBase.cpp +++ b/Source/Core/VideoCommon/MainBase.cpp @@ -192,7 +192,6 @@ void VideoBackendBase::InitializeShared() g_Config.Refresh(); g_Config.UpdateProjectionHack(); - g_Config.VerifyValidity(); UpdateActiveConfig(); } diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index d4097e5669..f561f94d37 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -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; }