From 1badceb455dae28a93a51da6c5cda0b510f93701 Mon Sep 17 00:00:00 2001 From: Filoppi Date: Wed, 17 Nov 2021 22:55:02 +0200 Subject: ControllerInterface: fix UpdateReferences() deadlock Removed useless locks to DeviceContainer::m_devices_mutex, as they were all already protected by m_devices_population_mutex. We have no interest in blocking other threads that were potentially reading devices at the same time so this seems fine. This simplifies the code, and I've adjusted a few comments which mentioned possible deadlock that should now be totally gone. The deadlock could have happen if a thread directly called EmulatedController::UpdateReferences(), while another another thread also reached EmulatedController::UpdateReferences() within a call to ControllerInterface::UpdateDevices(), as the mentioned function locked both the DeviceContainer::m_devices_mutex and s_get_state_mutex at the same time. The deadlock was frequent on game emulation startup on Android, due to the UpdateReferences() call in InputConfig::LoadConfig() and the UI thread triggering calls to ControllerInterface::UpdateDevices(). It could also have happened on Desktop if a user pressed "Refresh Devices" manually in the UI while the input config was loading. Also brought some UpdateReferences() comments and thread safety fixes from https://github.com/dolphin-emu/dolphin/pull/9489 --- Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp') diff --git a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp index c804e303f2..9cd7ced6f9 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp @@ -18,6 +18,8 @@ namespace ControllerEmu { +// This should theoretically be per EmulatedController instance, +// though no EmulatedController usually run in parallel, so it makes little difference static std::recursive_mutex s_get_state_mutex; std::string EmulatedController::GetDisplayName() const @@ -77,6 +79,7 @@ void EmulatedController::UpdateSingleControlReference(const ControllerInterface& { ciface::ExpressionParser::ControlEnvironment env(devi, GetDefaultDevice(), m_expression_vars); + const auto lock = GetStateLock(); ref->UpdateReference(env); env.CleanUnusedVariables(); -- cgit v1.2.3