Eeschema: fix crash caused by stale symbol library object pointers.

The new symbol library changes left stale pointers in the connection
graph because the SCH_COMPONENT object pins were not always getting
updated when a new copy of the library symbol was updated.

Force a full update of the connection graph whenever the schematic
library symbol links are refreshed.  This seems like overkill but it
ensures that there a no stale libraries items left in the connection
graph.

Fixes kicad/code/kicad#3658
This commit is contained in:
Wayne Stambaugh 2019-12-11 18:53:10 -05:00
parent 351e249105
commit ed025972ab
2 changed files with 26 additions and 34 deletions

View File

@ -186,15 +186,7 @@ SCH_COMPONENT::SCH_COMPONENT( const SCH_COMPONENT& aComponent ) :
for( SCH_FIELD& field : m_Fields ) for( SCH_FIELD& field : m_Fields )
field.SetParent( this ); field.SetParent( this );
m_pins = aComponent.m_pins; UpdatePins();
m_pinMap.clear();
// Re-parent the pins and build the pinMap
for( unsigned i = 0; i < m_pins.size(); ++i )
{
m_pins[ i ].SetParent( this );
m_pinMap[ m_pins[ i ].GetLibPin() ] = i;
}
m_fieldsAutoplaced = aComponent.m_fieldsAutoplaced; m_fieldsAutoplaced = aComponent.m_fieldsAutoplaced;
} }
@ -253,9 +245,15 @@ void SCH_COMPONENT::SetLibId( const LIB_ID& aLibId, PART_LIBS* aLibs )
SetModified(); SetModified();
if( aLibs ) if( aLibs )
{
Resolve( aLibs ); Resolve( aLibs );
}
else else
{
m_part.reset(); m_part.reset();
m_pins.clear();
m_pinMap.clear();
}
} }
} }
@ -288,6 +286,7 @@ void SCH_COMPONENT::SetLibId( const LIB_ID& aLibId, SYMBOL_LIB_TABLE* aSymLibTab
} }
m_part.reset( symbol.release() ); m_part.reset( symbol.release() );
UpdatePins();
} }
@ -319,7 +318,8 @@ bool SCH_COMPONENT::Resolve( PART_LIBS* aLibs )
// flimsy search path ordering. None-the-less find a part based on that design: // flimsy search path ordering. None-the-less find a part based on that design:
if( LIB_PART* part = aLibs->FindLibPart( m_lib_id ) ) if( LIB_PART* part = aLibs->FindLibPart( m_lib_id ) )
{ {
m_part.reset( part ); m_part.reset( new LIB_PART( *part ) );
UpdatePins();
return true; return true;
} }
@ -367,6 +367,7 @@ bool SCH_COMPONENT::Resolve( SYMBOL_LIB_TABLE& aLibTable, PART_LIB* aCacheLib )
if( part ) if( part )
{ {
m_part.reset( part.release() ); m_part.reset( part.release() );
UpdatePins();
return true; return true;
} }
} }
@ -380,6 +381,7 @@ bool SCH_COMPONENT::Resolve( SYMBOL_LIB_TABLE& aLibTable, PART_LIB* aCacheLib )
m_lib_id.Format().wx_str() ); m_lib_id.Format().wx_str() );
m_part.reset(); m_part.reset();
UpdatePins(); // This will clear the pin map and library symbol pin pointers.
return false; return false;
} }
@ -459,9 +461,11 @@ void SCH_COMPONENT::UpdatePins( const EE_COLLECTOR& aComponents )
void SCH_COMPONENT::UpdatePins( SCH_SHEET_PATH* aSheet ) void SCH_COMPONENT::UpdatePins( SCH_SHEET_PATH* aSheet )
{ {
m_pins.clear();
m_pinMap.clear();
if( m_part ) if( m_part )
{ {
m_pinMap.clear();
unsigned i = 0; unsigned i = 0;
for( LIB_PIN* libPin = m_part->GetNextPin(); libPin; libPin = m_part->GetNextPin( libPin ) ) for( LIB_PIN* libPin = m_part->GetNextPin(); libPin; libPin = m_part->GetNextPin( libPin ) )
@ -474,14 +478,7 @@ void SCH_COMPONENT::UpdatePins( SCH_SHEET_PATH* aSheet )
if( libPin->GetConvert() && m_convert && ( m_convert != libPin->GetConvert() ) ) if( libPin->GetConvert() && m_convert && ( m_convert != libPin->GetConvert() ) )
continue; continue;
if( m_pins.size() <= i || m_pins[ i ].GetLibPin() != libPin )
{
if( m_pins.size() > i )
m_pins.erase( m_pins.begin() + i, m_pins.end() );
m_pins.emplace_back( SCH_PIN( libPin, this ) ); m_pins.emplace_back( SCH_PIN( libPin, this ) );
}
m_pinMap[ libPin ] = i; m_pinMap[ libPin ] = i;
if( aSheet ) if( aSheet )
@ -490,11 +487,6 @@ void SCH_COMPONENT::UpdatePins( SCH_SHEET_PATH* aSheet )
++i; ++i;
} }
} }
else
{
m_pins.clear();
m_pinMap.clear();
}
} }
@ -998,7 +990,9 @@ void SCH_COMPONENT::SwapData( SCH_ITEM* aItem )
LIB_PART* part = component->m_part.release(); LIB_PART* part = component->m_part.release();
component->m_part.reset( m_part.release() ); component->m_part.reset( m_part.release() );
component->UpdatePins();
m_part.reset( part ); m_part.reset( part );
UpdatePins();
std::swap( m_Pos, component->m_Pos ); std::swap( m_Pos, component->m_Pos );
std::swap( m_unit, component->m_unit ); std::swap( m_unit, component->m_unit );
@ -1813,15 +1807,7 @@ SCH_COMPONENT& SCH_COMPONENT::operator=( const SCH_ITEM& aItem )
for( SCH_FIELD& field : m_Fields ) for( SCH_FIELD& field : m_Fields )
field.SetParent( this ); field.SetParent( this );
m_pins = c->m_pins; // std::vector's assignment operator UpdatePins();
m_pinMap.clear();
// Re-parent the pins and build the pinMap
for( unsigned i = 0; i < m_pins.size(); ++i )
{
m_pins[ i ].SetParent( this );
m_pinMap[ m_pins[ i ].GetLibPin() ] = i;
}
} }
return *this; return *this;

View File

@ -45,6 +45,7 @@
#include <netlist.h> #include <netlist.h>
#include <netlist_object.h> #include <netlist_object.h>
#include <class_library.h> #include <class_library.h>
#include <connection_graph.h>
#include <sch_junction.h> #include <sch_junction.h>
#include <sch_bus_entry.h> #include <sch_bus_entry.h>
#include <sch_line.h> #include <sch_line.h>
@ -1198,6 +1199,12 @@ void SCH_SCREENS::UpdateSymbolLinks( bool aForce )
{ {
for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() ) for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
screen->UpdateSymbolLinks( aForce ); screen->UpdateSymbolLinks( aForce );
SCH_SHEET_LIST sheets( g_RootSheet );
// All of the library symbols have been replaced with copies so the connection graph
// pointer are stale.
g_ConnectionGraph->Recalculate( sheets, true );
} }
@ -1232,7 +1239,6 @@ void SCH_SCREENS::TestDanglingEnds()
for( size_t ii = 0; ii < parallelThreadCount; ++ii ) for( size_t ii = 0; ii < parallelThreadCount; ++ii )
returns[ii].wait(); returns[ii].wait();
} }
} }