Catch some crashes on shutdown

These can happen when a tool is active that sends signals when exiting
(e.g. deselectEvent).  These may be caught by the active loop in another
tool which might try to update the UI after it has been freed.  By
marking all tools as "shutdown", the only event returned to them should
be null.  As an extra precaution, we flag the shutdown globally within
the tool manager and check this flag before launching either events or
new tools

Fixes https://gitlab.com/kicad/code/kicad/issues/10698

(cherry picked from commit db4f2d9dd8)
This commit is contained in:
Seth Hillbrand 2022-07-15 16:37:33 -07:00
parent a8c0bc0430
commit 995b2c517d
2 changed files with 25 additions and 1 deletions

View File

@ -206,7 +206,8 @@ TOOL_MANAGER::TOOL_MANAGER() :
m_warpMouseAfterContextMenu( true ), m_warpMouseAfterContextMenu( true ),
m_menuActive( false ), m_menuActive( false ),
m_menuOwner( -1 ), m_menuOwner( -1 ),
m_activeState( nullptr ) m_activeState( nullptr ),
m_shuttingDown( false )
{ {
m_actionMgr = new ACTION_MANAGER( this ); m_actionMgr = new ACTION_MANAGER( this );
} }
@ -313,6 +314,9 @@ VECTOR2D TOOL_MANAGER::GetCursorPosition() const
bool TOOL_MANAGER::RunAction( const TOOL_ACTION& aAction, bool aNow, void* aParam ) bool TOOL_MANAGER::RunAction( const TOOL_ACTION& aAction, bool aNow, void* aParam )
{ {
if( m_shuttingDown )
return true;
bool handled = false; bool handled = false;
TOOL_EVENT event = aAction.MakeEvent(); TOOL_EVENT event = aAction.MakeEvent();
@ -446,10 +450,22 @@ bool TOOL_MANAGER::runTool( TOOL_BASE* aTool )
void TOOL_MANAGER::ShutdownAllTools() void TOOL_MANAGER::ShutdownAllTools()
{ {
m_shuttingDown = true;
// Create a temporary list of tools to iterate over since when the tools shutdown // Create a temporary list of tools to iterate over since when the tools shutdown
// they remove themselves from the list automatically (invalidating the iterator) // they remove themselves from the list automatically (invalidating the iterator)
ID_LIST tmpList = m_activeTools; ID_LIST tmpList = m_activeTools;
// Make sure each tool knows that it is shutting down, so that loops get shut down
// at the dispatcher
for( auto id : tmpList )
{
if( m_toolIdIndex.count( id ) == 0 )
continue;
m_toolIdIndex[id]->shutdown = true;
}
for( auto id : tmpList ) for( auto id : tmpList )
{ {
ShutdownTool( id ); ShutdownTool( id );
@ -949,6 +965,11 @@ TOOL_MANAGER::ID_LIST::iterator TOOL_MANAGER::finishTool( TOOL_STATE* aState )
bool TOOL_MANAGER::ProcessEvent( const TOOL_EVENT& aEvent ) bool TOOL_MANAGER::ProcessEvent( const TOOL_EVENT& aEvent )
{ {
// Once the tool manager is shutting down, don't start
// activating more tools
if( m_shuttingDown )
return true;
bool handled = processEvent( aEvent ); bool handled = processEvent( aEvent );
TOOL_STATE* activeTool = GetCurrentToolState(); TOOL_STATE* activeTool = GetCurrentToolState();

View File

@ -578,6 +578,9 @@ private:
///< Pointer to the state object corresponding to the currently executed tool. ///< Pointer to the state object corresponding to the currently executed tool.
TOOL_STATE* m_activeState; TOOL_STATE* m_activeState;
///< True if the tool manager is shutting down (don't process additional events)
bool m_shuttingDown;
}; };
#endif // __TOOL_MANAGER_H #endif // __TOOL_MANAGER_H