Skip to content

Fix intermittent double-free crash in IBM_Cylinder (PointLinkedList)#83

Draft
Copilot wants to merge 2 commits into
developfrom
copilot/investigate-race-conditions
Draft

Fix intermittent double-free crash in IBM_Cylinder (PointLinkedList)#83
Copilot wants to merge 2 commits into
developfrom
copilot/investigate-race-conditions

Conversation

Copilot AI commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

The IBM_Cylinder CI test failed non-deterministically with free(): double free detected in tcache 2 → SIGABRT inside PointLinkedList_Destruct, called from ConvexHullOBB_constructIBM_construct.

Root cause

PointLinkedList in TessellationTypes.f90 maintained a NumOfPoints counter that was never initialized and never updated by any list operation. The destructor used this garbage value to drive its deallocation loop:

  • If garbage value < actual count → memory leak (silent, test passes)
  • If garbage value > actual count → loop follows circular pointers back into already-freed nodes → double-free crash

Which outcome occurred depended on what happened to be in that memory location, explaining the intermittent failure.

A secondary bug: the original destructor loop (do i = 2, NumOfPoints) freed only N−1 nodes, always leaking the last one, and on its final iteration read current%next from already-freed memory.

Changes (TessellationTypes.f90)

  • PointLinkedList_Construct — initialize NumOfPoints = 0
  • PointLinkedList_Add — increment NumOfPoints after insertion
  • PointLinkedList_RemoveLast — decrement NumOfPoints after removal
  • PointLinkedList_Remove — decrement NumOfPoints after removal
  • PointLinkedList_Destruct — restructure loop to free all N nodes without reading from freed memory; nullify head on both exit paths
! Before: loop i=2..N frees only N-1 nodes, reads freed head%next on last iteration
do i = 2, this% NumOfPoints
   deallocate(current)
   current => next
   next    => current% next   ! UB on last iter: next points to freed head
end do

! After: clean separation of "advance next" from "free current"
do i = 1, this% NumOfPoints - 1
   next => current% next
   deallocate(current)
   current => next
end do
deallocate(current)  ! free last node
nullify(this% head)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses a non-deterministic double-free crash in the IBM_Cylinder CI path by fixing PointLinkedList bookkeeping and making PointLinkedList_Destruct free nodes safely based on an accurate node count.

Changes:

  • Initialize PointLinkedList%NumOfPoints to 0 in the list constructor.
  • Maintain NumOfPoints correctly on add/remove operations.
  • Rework PointLinkedList_Destruct to deallocate all nodes without dereferencing freed memory, and nullify head on exit.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 391 to +395
end if

nullify(current, currentNext)

this% NumOfPoints = this% NumOfPoints + 1
@codecov

codecov Bot commented Jun 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 54.54545% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
Solver/src/libs/mesh/TessellationTypes.f90 54.54% 3 Missing and 2 partials ⚠️

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants