InputManager: Fix possible use-after-free on source reload

This commit is contained in:
Stenzek
2025-12-06 15:48:26 +10:00
parent ea4933abe5
commit f7ca150c79
4 changed files with 22 additions and 21 deletions

View File

@@ -1259,8 +1259,7 @@ void System::LoadSettings(bool display_osd_messages)
Settings::UpdateLogConfig(si);
Host::LoadSettings(si, lock);
InputManager::ReloadSources(controller_si, lock);
InputManager::ReloadBindings(controller_si, hotkey_si);
InputManager::ReloadSourcesAndBindings(controller_si, hotkey_si, lock);
// apply compatibility settings
if (g_settings.apply_compatibility_settings && s_state.running_game_entry)
@@ -1276,14 +1275,8 @@ void System::ReloadInputSources()
{
auto lock = Host::GetSettingsLock();
const SettingsInterface& controller_si = GetControllerSettingsLayer(lock);
InputManager::ReloadSources(controller_si, lock);
// skip loading bindings if we're not running, since it'll get done on startup anyway
if (IsValid())
{
const SettingsInterface& hotkey_si = GetHotkeySettingsLayer(lock);
InputManager::ReloadBindings(controller_si, hotkey_si);
}
const SettingsInterface& hotkey_si = GetHotkeySettingsLayer(lock);
InputManager::ReloadSourcesAndBindings(controller_si, hotkey_si, lock);
}
void System::ReloadInputBindings()

View File

@@ -640,10 +640,7 @@ std::optional<WindowInfo> Host::AcquireRenderWindow(RenderAPI render_api, bool f
s_state.platform_window_updated.Wait();
// reload input sources, since it might use the window handle
{
auto lock = Host::GetSettingsLock();
InputManager::ReloadSources(*Host::GetSettingsInterface(), lock);
}
Host::RunOnCPUThread(&System::ReloadInputSources);
return wi;
}

View File

@@ -143,6 +143,7 @@ static float ApplySingleBindingScale(float sensitivity, float deadzone, float va
static void AddHotkeyBindings(const SettingsInterface& si);
static void AddPadBindings(const SettingsInterface& si, const std::string& section, u32 pad,
const Controller::ControllerInfo& cinfo);
static void InternalReloadBindings(const SettingsInterface& binding_si, const SettingsInterface& hotkey_binding_si);
static void SynchronizePadEffectBindings(InputBindingKey key);
static void UpdateContinuedVibration();
static void GenerateRelativeMouseEvents();
@@ -2150,12 +2151,9 @@ bool InputManager::DoEventHook(InputBindingKey key, float value)
// Binding Updater
// ------------------------------------------------------------------------
void InputManager::ReloadBindings(const SettingsInterface& binding_si, const SettingsInterface& hotkey_binding_si)
void InputManager::InternalReloadBindings(const SettingsInterface& binding_si,
const SettingsInterface& hotkey_binding_si)
{
PauseVibration();
std::unique_lock lock(s_state.mutex);
s_state.binding_map.clear();
s_state.pad_vibration_array.clear();
s_state.pad_led_array.clear();
@@ -2190,6 +2188,14 @@ void InputManager::ReloadBindings(const SettingsInterface& binding_si, const Set
TinyString::from_format("Pointer{}Scale", s_pointer_axis_names[axis]).c_str(), default_scale),
1.0f);
}
}
void InputManager::ReloadBindings(const SettingsInterface& binding_si, const SettingsInterface& hotkey_binding_si)
{
PauseVibration();
std::unique_lock lock(s_state.mutex);
InternalReloadBindings(binding_si, hotkey_binding_si);
UpdateRelativeMouseMode();
}
@@ -2398,7 +2404,8 @@ void InputManager::UpdateInputSourceState(const SettingsInterface& si, std::uniq
}
}
void InputManager::ReloadSources(const SettingsInterface& si, std::unique_lock<std::mutex>& settings_lock)
void InputManager::ReloadSourcesAndBindings(const SettingsInterface& si, const SettingsInterface& hotkey_binding_si,
std::unique_lock<std::mutex>& settings_lock)
{
std::unique_lock lock(s_state.mutex);
@@ -2415,6 +2422,9 @@ void InputManager::ReloadSources(const SettingsInterface& si, std::unique_lock<s
#endif
UpdatePointerCount();
InternalReloadBindings(si, hotkey_binding_si);
UpdateRelativeMouseMode();
}
ForceFeedbackDevice::~ForceFeedbackDevice()

View File

@@ -294,7 +294,8 @@ void SynchronizeBindingHandlerState();
void ReloadBindings(const SettingsInterface& si, const SettingsInterface& hotkey_binding_si);
/// Re-parses the sources part of the config and initializes any backends.
void ReloadSources(const SettingsInterface& si, std::unique_lock<std::mutex>& settings_lock);
void ReloadSourcesAndBindings(const SettingsInterface& si, const SettingsInterface& hotkey_binding_si,
std::unique_lock<std::mutex>& settings_lock);
/// Called when a device change is triggered by the system (DBT_DEVNODES_CHANGED on Windows).
/// Returns true if any device changes are detected.