Fix hotkey processing locking issue.

Rather than manually release the lock inside the loop, which breaks RAII
and introduces undefined behavior, we separate the controller state gathering
operation from the rumble hotkey processing loop. The lock lifecycle
is now automatically managed by scope.

On a side note, with multiple controllers connected this would probably
have become clear that it's broken sooner but I guess that's not a very
common use case.
This commit is contained in:
Herman S.
2025-08-30 17:12:45 +09:00
committed by Radosław Gliński
parent 765073021a
commit 4d1380decb

View File

@@ -1896,19 +1896,26 @@ void EmulatorWindow::GamepadHotKeys() {
if (input_sys) {
while (true) {
auto input_lock = input_sys->lock();
// Collect controller states while holding the lock
std::array<std::pair<bool, X_INPUT_STATE>, XUserMaxUserCount>
controller_states;
{
auto input_lock = input_sys->lock();
for (uint32_t user_index = 0; user_index < XUserMaxUserCount;
++user_index) {
X_RESULT result = input_sys->GetState(
user_index, X_INPUT_FLAG::X_INPUT_FLAG_GAMEPAD, &state);
controller_states[user_index] = {result == X_ERROR_SUCCESS, state};
}
} // Lock is released here when input_lock goes out of scope
// Process hotkeys without holding the lock
for (uint32_t user_index = 0; user_index < XUserMaxUserCount;
++user_index) {
X_RESULT result = input_sys->GetState(
user_index, X_INPUT_FLAG::X_INPUT_FLAG_GAMEPAD, &state);
// Release the lock before processing the hotkey
input_lock.mutex()->unlock();
// Check if the controller is connected
if (result == X_ERROR_SUCCESS) {
if (ProcessControllerHotkey(state.gamepad.buttons).rumble) {
if (controller_states[user_index].first) {
if (ProcessControllerHotkey(
controller_states[user_index].second.gamepad.buttons)
.rumble) {
// Enable Vibration
VibrateController(input_sys, user_index, true);