diff --git a/GCPad_Lib/src/GamepadManager.cpp b/GCPad_Lib/src/GamepadManager.cpp index 93b3c35..7cebbfa 100644 --- a/GCPad_Lib/src/GamepadManager.cpp +++ b/GCPad_Lib/src/GamepadManager.cpp @@ -276,10 +276,17 @@ void GamepadManagerImpl::setGamepadDisconnectedCallback(GamepadDisconnectedCallb } void GamepadManagerImpl::updateAll() { + // Lock against the hotplug thread. Without this, updateAll() (called every + // frame from the polling thread) iterates gamepads_ and dereferences each + // device while the hotplug thread can simultaneously destroy a device in + // check_for_disconnected_devices() (gamepads_[i].reset()) — a data race and + // use-after-free that crashed the host whenever a pad dropped mid-frame. + // The hotplug thread already uses try_lock_for and simply skips a cycle if + // it can't acquire the lock, so this can never deadlock game launch. + std::lock_guard lock(mutex_); for (auto& gamepad : gamepads_) { if (gamepad) { - if (!gamepad->updateState()) { - } + gamepad->updateState(); } } }