From 227f264838e199f606ad4c9721bab9147949c1b4 Mon Sep 17 00:00:00 2001 From: "R. Timothy Edwards" Date: Sun, 9 Nov 2025 12:52:03 -0500 Subject: [PATCH] Fixed the error that causes problems with the tile allocation. The error was in selStretchEraseFunc2() which was calling DBErase(). But DBErase() can call DBSrPaintArea() and thereby start another search of the same plane while the plane is already in a search. This is absolutely invalid. However, it is simple just to use selStretchEraseFunc2() to collect a mask of the types that need to be erased and pass that back to the caller, and apply DBErase() to each type in the mask, outside of the DBSrPaintArea() search. With this fix, the tile allocation is no longer causing problems, and the code to add tiles deallocated by TiJoinX and TiJoinY to the free tile list has been uncommented again. --- VERSION | 2 +- select/selOps.c | 25 +++++++++++++++++++------ tiles/tile.c | 4 ++-- tiles/tile.h | 4 ++-- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/VERSION b/VERSION index 651b6b08..58fd125c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.575 +8.3.576 diff --git a/select/selOps.c b/select/selOps.c index 08602477..ce24d8c4 100644 --- a/select/selOps.c +++ b/select/selOps.c @@ -60,6 +60,7 @@ typedef struct planeAndArea int pa_plane; /* Plane of interest */ Rect *pa_area; /* Area affected */ TileTypeBitMask *pa_mask; /* Mask used in plane search */ + TileTypeBitMask pa_rmask; /* Mask to generate during search */ } planeAndArea; /* The following structure type is used to build up a list of areas @@ -1739,9 +1740,18 @@ selStretchEraseFunc(tile, plane) pa.pa_area = &editArea; pa.pa_plane = planeNum; pa.pa_mask = &tmpmask; + TTMaskZero(&pa.pa_rmask); + + /* Find all the types that need to be erased inside editArea and + * generate a mask from them. Then erase each type. + */ DBSrPaintArea((Tile *)NULL, EditCellUse->cu_def->cd_planes[planeNum], &editArea, &tmpmask, selStretchEraseFunc2, (ClientData)&pa); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (TTMaskHasType(&pa.pa_rmask, t)) + DBErase(EditCellUse->cu_def, &editArea, t); + ui.pu_pNum = planeNum; ui.pu_def = EditCellUse->cu_def; DBPaintPlane(EditCellUse->cu_def->cd_planes[planeNum], &editArea, @@ -1755,18 +1765,21 @@ selStretchEraseFunc2(tile, pa) Tile *tile; planeAndArea *pa; { + TileType type = TT_SPACE; + if (IsSplit(tile)) { if (TTMaskHasType(pa->pa_mask, TiGetLeftType(tile))) - DBErase(EditCellUse->cu_def, pa->pa_area, - DBPlaneToResidue(TiGetLeftType(tile), pa->pa_plane)); + type = DBPlaneToResidue(TiGetLeftType(tile), pa->pa_plane); if (TTMaskHasType(pa->pa_mask, TiGetRightType(tile))) - DBErase(EditCellUse->cu_def, pa->pa_area, - DBPlaneToResidue(TiGetRightType(tile), pa->pa_plane)); + type = DBPlaneToResidue(TiGetRightType(tile), pa->pa_plane); } else - DBErase(EditCellUse->cu_def, pa->pa_area, - DBPlaneToResidue(TiGetType(tile), pa->pa_plane)); + type = DBPlaneToResidue(TiGetType(tile), pa->pa_plane); + + if (type != TT_SPACE) + TTMaskSetType(&pa->pa_rmask, type); + return 0; } diff --git a/tiles/tile.c b/tiles/tile.c index c2652b77..778d1f9f 100644 --- a/tiles/tile.c +++ b/tiles/tile.c @@ -820,7 +820,7 @@ TiJoinX1(Tile **delay1, Tile *tile1, Tile *tile2, Plane *plane) { TiFreeIf(*delay1); TiJoinX(tile1, tile2, plane); - // *delay1 = tile2; + *delay1 = tile2; } void @@ -828,7 +828,7 @@ TiJoinY1(Tile **delay1, Tile *tile1, Tile *tile2, Plane *plane) { TiFreeIf(*delay1); TiJoinY(tile1, tile2, plane); - // *delay1 = tile2; + *delay1 = tile2; } #endif diff --git a/tiles/tile.h b/tiles/tile.h index a63b614f..3acc23f0 100644 --- a/tiles/tile.h +++ b/tiles/tile.h @@ -307,7 +307,7 @@ TiJoinX1(Tile **delay1, Tile *tile1, Tile *tile2, Plane *plane) { TiFreeIf(*delay1); TiJoinX(tile1, tile2, plane); - // *delay1 = tile2; + *delay1 = tile2; } inline void @@ -315,7 +315,7 @@ TiJoinY1(Tile **delay1, Tile *tile1, Tile *tile2, Plane *plane) { TiFreeIf(*delay1); TiJoinY(tile1, tile2, plane); - // *delay1 = tile2; + *delay1 = tile2; } #else /* To support older compilers (that don't auto emit based on -O level) */