From 485e89f7a5f06cb0e85ac38705e35f3b3f966476 Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Fri, 4 Mar 2022 10:45:49 -0800 Subject: [PATCH] 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 8218f9ab44e9aa1ce8ec6ce4ce9b7d6b34eadc7c) --- pcbnew/zone.cpp | 41 ++++++----------------------------------- 1 file changed, 6 insertions(+), 35 deletions(-) diff --git a/pcbnew/zone.cpp b/pcbnew/zone.cpp index 6290b36c4d..f897006309 100644 --- a/pcbnew/zone.cpp +++ b/pcbnew/zone.cpp @@ -971,54 +971,25 @@ void ZONE::HatchBorder() min_a += offset; // loop through hatch lines - #define MAXPTS 200 // Usually we store only few values per one hatch line - // depending on the complexity of the zone outline - - static std::vector pointbuffer; - pointbuffer.clear(); - pointbuffer.reserve( MAXPTS + 2 ); + std::vector pointbuffer; + pointbuffer.reserve( 256 ); 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(); // Iterate through all vertices for( auto iterator = m_Poly->IterateSegmentsWithHoles(); iterator; iterator++ ) { double x, y; - bool ok; SEG segment = *iterator; - ok = FindLineSegmentIntersection( a, slope, segment.A.x, segment.A.y, segment.B.x, - segment.B.y, x, y ); - - if( ok ) - { - VECTOR2I point( KiROUND( x ), KiROUND( y ) ); - pointbuffer.push_back( point ); - } - - if( pointbuffer.size() >= MAXPTS ) // overflow - { - wxASSERT( 0 ); - break; - } + if( FindLineSegmentIntersection( a, slope, segment.A.x, segment.A.y, segment.B.x, + segment.B.y, x, y ) ) + pointbuffer.emplace_back( KiROUND( x ), KiROUND( y ) ); } - // 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 // ensure the starting point and the ending point of the same segment // are stored one just after the other. @@ -1026,7 +997,7 @@ void ZONE::HatchBorder() sort( pointbuffer.begin(), pointbuffer.end(), sortEndsByDescendingX ); // 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;