[hid_core] fix LM2 crash due to callbacks not being removed properly (#4178)

the function returned the key AFTER this one, which points to an invalid object
basically its like "oh im returning the index AFTER Myself"
off-by-1 error basically; now it returns OUR own key.

Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4178
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
This commit is contained in:
lizzie 2026-07-07 19:52:22 +02:00 • committed by crueter
parent bfc0e60333
commit 6119e8fad2
No known key found for this signature in database
GPG key ID: 425ACD2D4830EBC6
7 changed files with 51 additions and 53 deletions

View file

@ -1,7 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/settings.h"
#include "common/assert.h"
#include "hid_core/frontend/emulated_console.h"
#include "hid_core/frontend/input_converter.h"
@ -308,17 +312,15 @@ void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) {
int EmulatedConsole::SetCallback(ConsoleUpdateCallback update_callback) {
std::scoped_lock lock{callback_mutex};
++last_callback_key;
callback_list.insert_or_assign(last_callback_key, std::move(update_callback));
return last_callback_key++;
return last_callback_key;
}
void EmulatedConsole::DeleteCallback(int key) {
std::scoped_lock lock{callback_mutex};
const auto& iterator = callback_list.find(key);
if (iterator == callback_list.end()) {
LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
return;
}
callback_list.erase(iterator);
auto const it = callback_list.find(key);
ASSERT_MSG(it != callback_list.end(), "Tried to delete non-existent callback {}", key);
callback_list.erase(it);
}
} // namespace Core::HID

View file

@ -10,6 +10,7 @@
#include <ranges>
#include "common/thread.h"
#include "common/assert.h"
#include "hid_core/frontend/emulated_controller.h"
#include "hid_core/frontend/input_converter.h"
#include "hid_core/hid_util.h"
@ -1876,12 +1877,9 @@ NpadColor EmulatedController::GetNpadColor(u32 color) {
void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) {
std::unique_lock lock{callback_mutex};
for (const auto& poller_pair : callback_list) {
const ControllerUpdateCallback& poller = poller_pair.second;
if (!is_npad_service_update && poller.is_npad_service) {
continue;
}
if (poller.on_change) {
for (auto const& p : callback_list) {
auto const& poller = p.second;
if (is_npad_service_update || !poller.is_npad_service) {
poller.on_change(type);
}
}
@ -1889,18 +1887,16 @@ void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npa
int EmulatedController::SetCallback(ControllerUpdateCallback update_callback) {
std::unique_lock lock{callback_mutex};
++last_callback_key;
callback_list.insert_or_assign(last_callback_key, std::move(update_callback));
return last_callback_key++;
return last_callback_key;
}
void EmulatedController::DeleteCallback(int key) {
std::unique_lock lock{callback_mutex};
const auto& iterator = callback_list.find(key);
if (iterator == callback_list.end()) {
LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
return;
}
callback_list.erase(iterator);
auto const it = callback_list.find(key);
ASSERT_MSG(it != callback_list.end(), "Tried to delete non-existent callback {}", key);
callback_list.erase(it);
}
void EmulatedController::StatusUpdate() {

View file

@ -1,9 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <fmt/ranges.h>
#include "common/assert.h"
#include "hid_core/frontend/emulated_devices.h"
#include "hid_core/frontend/input_converter.h"
@ -467,17 +471,15 @@ void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) {
int EmulatedDevices::SetCallback(InterfaceUpdateCallback update_callback) {
std::scoped_lock lock{callback_mutex};
++last_callback_key;
callback_list.insert_or_assign(last_callback_key, std::move(update_callback));
return last_callback_key++;
return last_callback_key;
}
void EmulatedDevices::DeleteCallback(int key) {
std::scoped_lock lock{callback_mutex};
const auto& iterator = callback_list.find(key);
if (iterator == callback_list.end()) {
LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
return;
}
callback_list.erase(iterator);
auto const it = callback_list.find(key);
ASSERT_MSG(it != callback_list.end(), "Tried to delete non-existent callback {}", key);
callback_list.erase(it);
}
} // namespace Core::HID