From f39460e617d56358c83c8227203b83f547d386e5 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Thu, 3 Jun 2021 20:08:51 -0700 Subject: [PATCH] Fix rare re-entrancy issue with CCryEditApp::IdleProcessing (#1134) This issue manifested in a crash in rare circumstances when the Editor lost and gained focus while a modal dialog was active. After investigation, it was discovered that native event processing can lead to IdleProcessing being called again from the main thread while idle processing is still happening. As this is unintentional and generally undesirable, we now guard against this within the IdleProcessing method. --- Code/Sandbox/Editor/CryEdit.cpp | 8 ++++++++ Code/Sandbox/Editor/CryEdit.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/Code/Sandbox/Editor/CryEdit.cpp b/Code/Sandbox/Editor/CryEdit.cpp index c723e6049a..a972a4bd9b 100644 --- a/Code/Sandbox/Editor/CryEdit.cpp +++ b/Code/Sandbox/Editor/CryEdit.cpp @@ -2281,6 +2281,14 @@ int CCryEditApp::IdleProcessing(bool bBackgroundUpdate) return 0; } + // Ensure we don't get called re-entrantly + // This can occur when a nested Qt event loop fires (e.g. by way of a modal dialog calling exec) + if (m_idleProcessingRunning) + { + return 0; + } + QScopedValueRollback guard(m_idleProcessingRunning, true); + //////////////////////////////////////////////////////////////////////// // Call the update function of the engine //////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Editor/CryEdit.h b/Code/Sandbox/Editor/CryEdit.h index dc4f015faf..e37fb53561 100644 --- a/Code/Sandbox/Editor/CryEdit.h +++ b/Code/Sandbox/Editor/CryEdit.h @@ -335,6 +335,8 @@ private: // If this flag is set, the next OnIdle() will update, even if the app is in the background, and then // this flag will be reset. bool m_bForceProcessIdle = false; + // This is set while IdleProcessing is running to prevent re-entrancy + bool m_idleProcessingRunning = false; // Keep the editor alive, even if no focus is set bool m_bKeepEditorActive = false; // Currently creating a new level