Finally found the intermittant QA crash

When loading footprints/zones in parallel, we cannot reference a static
vector that gets cleared by other threads.

It is unclear why this element was ever static to begin with (premature
optimization?) but it has been this way for a long time.  We never
noticed until we threaded load cycles, which gave the hatch a chance to
override itself and cause crashes

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

(cherry picked from commit 8218f9ab44)
This commit is contained in:
Seth Hillbrand 2022-03-04 10:45:49 -08:00
parent 611311697e
commit 485e89f7a5
1 changed files with 6 additions and 35 deletions

View File

@ -971,54 +971,25 @@ void ZONE::HatchBorder()
min_a += offset; min_a += offset;
// loop through hatch lines // loop through hatch lines
#define MAXPTS 200 // Usually we store only few values per one hatch line std::vector<VECTOR2I> pointbuffer;
// depending on the complexity of the zone outline pointbuffer.reserve( 256 );
static std::vector<VECTOR2I> pointbuffer;
pointbuffer.clear();
pointbuffer.reserve( MAXPTS + 2 );
for( int a = min_a; a < max_a; a += spacing ) for( int a = min_a; a < max_a; a += spacing )
{ {
// get intersection points for this hatch line
// Note: because we should have an even number of intersections with the
// current hatch line and the zone outline (a closed polygon,
// or a set of closed polygons), if an odd count is found
// we skip this line (should not occur)
pointbuffer.clear(); pointbuffer.clear();
// Iterate through all vertices // Iterate through all vertices
for( auto iterator = m_Poly->IterateSegmentsWithHoles(); iterator; iterator++ ) for( auto iterator = m_Poly->IterateSegmentsWithHoles(); iterator; iterator++ )
{ {
double x, y; double x, y;
bool ok;
SEG segment = *iterator; SEG segment = *iterator;
ok = FindLineSegmentIntersection( a, slope, segment.A.x, segment.A.y, segment.B.x, if( FindLineSegmentIntersection( a, slope, segment.A.x, segment.A.y, segment.B.x,
segment.B.y, x, y ); segment.B.y, x, y ) )
pointbuffer.emplace_back( KiROUND( x ), KiROUND( y ) );
if( ok )
{
VECTOR2I point( KiROUND( x ), KiROUND( y ) );
pointbuffer.push_back( point );
}
if( pointbuffer.size() >= MAXPTS ) // overflow
{
wxASSERT( 0 );
break;
}
} }
// ensure we have found an even intersection points count
// because intersections are the ends of segments
// inside the polygon(s) and a segment has 2 ends.
// if not, this is a strange case (a bug ?) so skip this hatch
if( pointbuffer.size() % 2 != 0 )
continue;
// sort points in order of descending x (if more than 2) to // sort points in order of descending x (if more than 2) to
// ensure the starting point and the ending point of the same segment // ensure the starting point and the ending point of the same segment
// are stored one just after the other. // are stored one just after the other.
@ -1026,7 +997,7 @@ void ZONE::HatchBorder()
sort( pointbuffer.begin(), pointbuffer.end(), sortEndsByDescendingX ); sort( pointbuffer.begin(), pointbuffer.end(), sortEndsByDescendingX );
// creates lines or short segments inside the complex polygon // creates lines or short segments inside the complex polygon
for( unsigned ip = 0; ip < pointbuffer.size(); ip += 2 ) for( size_t ip = 0; ip + 1 < pointbuffer.size(); ip += 2 )
{ {
int dx = pointbuffer[ip + 1].x - pointbuffer[ip].x; int dx = pointbuffer[ip + 1].x - pointbuffer[ip].x;