Fix a threading segfault when filling zones

The shape cache gets reset by the zone fill algorithm.  This needs to be
cleaned before multiple threads are created and cannot be modified when
threading.

Fixes https://gitlab.com/kicad/code/kicad/issues/4723
This commit is contained in:
Seth Hillbrand 2020-06-28 11:00:40 -07:00
parent f5842156a5
commit 224b41e8b1
3 changed files with 27 additions and 14 deletions

View File

@ -193,7 +193,7 @@ void D_PAD::SetChamferRectRatio( double aChamferScale )
const std::vector<std::shared_ptr<SHAPE>>& D_PAD::GetEffectiveShapes() const
{
if( m_shapesDirty )
buildEffectiveShapes();
BuildEffectiveShapes();
return m_effectiveShapes;
}
@ -202,7 +202,7 @@ const std::vector<std::shared_ptr<SHAPE>>& D_PAD::GetEffectiveShapes() const
const std::shared_ptr<SHAPE_SEGMENT>& D_PAD::GetEffectiveHoleShape() const
{
if( m_shapesDirty )
buildEffectiveShapes();
BuildEffectiveShapes();
return m_effectiveHoleShape;
}
@ -211,13 +211,13 @@ const std::shared_ptr<SHAPE_SEGMENT>& D_PAD::GetEffectiveHoleShape() const
int D_PAD::GetBoundingRadius() const
{
if( m_shapesDirty )
buildEffectiveShapes();
BuildEffectiveShapes();
return m_effectiveBoundingRadius;
}
void D_PAD::buildEffectiveShapes() const
void D_PAD::BuildEffectiveShapes() const
{
m_effectiveShapes.clear();
m_effectiveHoleShape = nullptr;

View File

@ -317,6 +317,8 @@ public:
void SetDrillShape( PAD_DRILL_SHAPE_T aShape ) { m_drillShape = aShape; m_shapesDirty = true; }
PAD_DRILL_SHAPE_T GetDrillShape() const { return m_drillShape; }
bool IsDirty() const { return m_shapesDirty; }
/**
* JEY TODO: temporary until Tom is done with DRC stuff....
*/
@ -575,6 +577,11 @@ public:
*/
bool PadShouldBeNPTH() const;
/**
* Rebuilds the shape cache for the pad and clears the dirty bit
*/
void BuildEffectiveShapes() const;
virtual void ViewGetLayers( int aLayers[], int& aCount ) const override;
virtual unsigned int ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override;
@ -597,8 +604,6 @@ private:
void addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError ) const;
void buildEffectiveShapes() const;
private:
wxString m_name; ///< pad name (pin number in schematic)
wxString m_pinFunction; ///< pin function in schematic

View File

@ -119,6 +119,16 @@ bool ZONE_FILLER::Fill( const std::vector<ZONE_CONTAINER*>& aZones, bool aCheck
m_boardOutline.RemoveAllContours();
m_brdOutlinesValid = m_board->GetBoardPolygonOutlines( m_boardOutline );
// Update the bounding box shape caches in the pads to prevent multi-threaded rebuilds
for( auto module : m_board->Modules() )
{
for( auto pad : module->Pads() )
{
if( pad->IsDirty() )
pad->BuildEffectiveShapes();
}
}
for( auto zone : aZones )
{
// Keepout zones are not filled
@ -949,16 +959,14 @@ void ZONE_FILLER::buildThermalSpokes( const ZONE_CONTAINER* aZone, PCB_LAYER_ID
//
// We use the bounding-box to lay out the spokes, but for this to work the
// bounding box has to be built at the same rotation as the spokes.
// We have to use a dummy pad to avoid dirtying the cached shapes
wxPoint shapePos = pad->ShapePos();
wxPoint padPos = pad->GetPosition();
double padAngle = pad->GetOrientation();
pad->SetOrientation( 0.0 );
pad->SetPosition( { 0, 0 } );
BOX2I reliefBB = pad->GetBoundingBox();
pad->SetPosition( padPos );
pad->SetOrientation( padAngle );
double padAngle = pad->GetOrientation();
D_PAD dummy_pad( *pad );
dummy_pad.SetOrientation( 0.0 );
dummy_pad.SetPosition( { 0, 0 } );
BOX2I reliefBB = dummy_pad.GetBoundingBox();
reliefBB.Inflate( thermalReliefGap + epsilon );
// For circle pads, the thermal spoke orientation is 45 deg