Skip to content

Commit b68fe2d

Browse files
authored
Merge pull request #428 from drbergman/fix-spring-attachment-race-upstream
Take spring attachments under the lock before iterating them
2 parents f8f0a06 + b995db6 commit b68fe2d

1 file changed

Lines changed: 17 additions & 2 deletions

File tree

‎core/PhysiCell_standard_models.cpp‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,10 +1466,25 @@ void dynamic_spring_attachments( Cell* pCell , Phenotype& phenotype, double dt )
14661466
{
14671467
// check for detachments
14681468
double detachment_probability = phenotype.mechanics.detachment_rate * dt;
1469+
1470+
// This runs inside the mechanics parallel-for, and this loop is not the only
1471+
// thing touching pCell's spring list: another thread running this same function
1472+
// for a neighbor calls attach_cells_as_spring(), which reaches into THIS cell's
1473+
// spring_attachments and push_back()s. Those writers serialize on the unnamed
1474+
// critical in Cell::attach_cell_as_spring() / detach_cell_as_spring(); reading
1475+
// here without it means a concurrent push_back that reallocates leaves the loop
1476+
// indexing a freed buffer and dereferencing garbage. Copy under the same lock
1477+
// and walk the copy.
1478+
// The lock is not held across the loop body: detach_cells_as_spring() takes the
1479+
// same unnamed critical, and OpenMP criticals are not reentrant.
1480+
std::vector<Cell*> spring_attachments_snapshot;
1481+
#pragma omp critical
1482+
{ spring_attachments_snapshot = pCell->state.spring_attachments; }
1483+
14691484
// detach_cells_as_spring swaps the detached cell with the last cell in the vector, so we need to iterate backwards
1470-
for( int j=pCell->state.spring_attachments.size()-1; j >= 0; j-- )
1485+
for( int j=spring_attachments_snapshot.size()-1; j >= 0; j-- )
14711486
{
1472-
Cell* pTest = pCell->state.spring_attachments[j];
1487+
Cell* pTest = spring_attachments_snapshot[j];
14731488
if (phenotype.cell_interactions.pAttackTarget==pTest || pTest->phenotype.cell_interactions.pAttackTarget==pCell) // do not let attackers detach randomly
14741489
{ continue; }
14751490
if( UniformRandom() <= detachment_probability )

0 commit comments

Comments
 (0)