From 9e48cc41567967623dd85db9bb9ee8847c9538d6 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 8 Apr 2026 17:13:34 +0200 Subject: [PATCH] Fix crash on leftover window handle inside an input device events queue --- Source/Engine/Input/Input.cpp | 23 +++++++++---------- Source/Engine/Platform/Base/WindowBase.cpp | 4 ---- .../Engine/Platform/Windows/WindowsWindow.cpp | 8 +------ 3 files changed, 12 insertions(+), 23 deletions(-) diff --git a/Source/Engine/Input/Input.cpp b/Source/Engine/Input/Input.cpp index 5b3660462..2dd80f923 100644 --- a/Source/Engine/Input/Input.cpp +++ b/Source/Engine/Input/Input.cpp @@ -89,17 +89,6 @@ Delegate Input::AxisValueChanged; Array Input::ActionMappings; Array Input::AxisMappings; -void ClearWindowInputs(Window* window) -{ - WindowsManager::WindowsLocker.Lock(); - for (int32 i = InputEvents.Count() - 1; i >= 0; i--) - { - if (InputEvents[i].Target == window) - InputEvents.RemoveAtKeepOrder(i); - } - WindowsManager::WindowsLocker.Unlock(); -} - void InputSettings::Apply() { PROFILE_MEM(Input); @@ -934,9 +923,10 @@ void InputService::Update() Input::GamepadsChanged(); } + WindowsManager::WindowsLocker.Lock(); + // Pick the first focused window for input events Window* defaultWindow = nullptr; - WindowsManager::WindowsLocker.Lock(); for (auto window : WindowsManager::Windows) { if (window->IsFocused() && window->GetSettings().AllowInput) @@ -945,6 +935,15 @@ void InputService::Update() break; } } + + // Remove events from destroyed windows + for (int32 i = InputEvents.Count() - 1; i >= 0; i--) + { + const auto& e = InputEvents[i]; + if (e.Target && !WindowsManager::Windows.Contains(e.Target)) + InputEvents.RemoveAtKeepOrder(i); + } + WindowsManager::WindowsLocker.Unlock(); // Send input events for the focused window diff --git a/Source/Engine/Platform/Base/WindowBase.cpp b/Source/Engine/Platform/Base/WindowBase.cpp index 4ff3ab61f..2d6d2d615 100644 --- a/Source/Engine/Platform/Base/WindowBase.cpp +++ b/Source/Engine/Platform/Base/WindowBase.cpp @@ -17,8 +17,6 @@ #include "Engine/Scripting/ManagedCLR/MMethod.h" #include "Engine/Scripting/ManagedCLR/MClass.h" -extern void ClearWindowInputs(Window* window); - #if USE_CSHARP // Helper macros for calling C# events #define BEGIN_INVOKE_EVENT(name, paramsCount) \ @@ -124,7 +122,6 @@ WindowBase::WindowBase(const CreateWindowSettings& settings) WindowBase::~WindowBase() { - ClearWindowInputs((Window*)this); ASSERT(!RenderTask); ASSERT(!_swapChain); WindowsManager::Unregister((Window*)this); @@ -186,7 +183,6 @@ String WindowBase::ToString() const void WindowBase::OnDeleteObject() { // Dereference window - ClearWindowInputs((Window*)this); #if !USE_EDITOR if (RenderTask && RenderTask == MainRenderTask::Instance) { diff --git a/Source/Engine/Platform/Windows/WindowsWindow.cpp b/Source/Engine/Platform/Windows/WindowsWindow.cpp index bb8575496..ba31ec647 100644 --- a/Source/Engine/Platform/Windows/WindowsWindow.cpp +++ b/Source/Engine/Platform/Windows/WindowsWindow.cpp @@ -181,13 +181,7 @@ WindowsWindow::~WindowsWindow() { if (HasHWND()) { - // Destroy window - if (DestroyWindow(_handle) == 0) - { - LOG(Warning, "DestroyWindow failed! Error: {0:#x}", GetLastError()); - } - - // Clear + DestroyWindow(_handle); _handle = nullptr; _visible = false; }