Skip to content

Commit 4832236

Browse files
authored
This fixes Github issue 78206 - a heap corruption problem associated with mark stack overflow (#78756)
* This fixes Github issue 78206 - a heap corruption problem associated with mark stack overflow. Dumps provided by the customer showed in all cases that the min_overflow_address/max_overflow_address fields had values different from their initial values of MAX_PTR and 0. This implies that a mark stack overflow has occurred, but has not been properly handled. Looking at the code, we realized that we may still have objects in the mark prefetch queue as we enter process_mark_overflow. These objects may cause another mark stack overflow when they are traced. So we need to drain the mark prefetch queue before we check the min_overflow_address/max_overflow_address fields. We provided a private build of clrgc.dll to the customer reporting the issue, and customer has validated that the fix resolves the issue. Looking at the code further, some calls to drain_mark_queue have now become superfluous because the mark queue is now guaranteed to be empty after calls to process_mark_overflow and scan_dependent handles. These calls have been replaced with calls to mark_queue.verify_empty.
1 parent 4b6380d commit 4832236

File tree

1 file changed

+9
-3
lines changed

1 file changed

+9
-3
lines changed

src/coreclr/gc/gc.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25971,6 +25971,7 @@ BOOL gc_heap::process_mark_overflow(int condemned_gen_number)
2597125971

2597225972
BOOL overflow_p = FALSE;
2597325973
recheck:
25974+
drain_mark_queue();
2597425975
if ((! (max_overflow_address == 0) ||
2597525976
! (min_overflow_address == MAX_PTR)))
2597625977
{
@@ -26235,7 +26236,8 @@ void gc_heap::scan_dependent_handles (int condemned_gen_number, ScanContext *sc,
2623526236
if (process_mark_overflow(condemned_gen_number))
2623626237
fUnscannedPromotions = true;
2623726238

26238-
drain_mark_queue();
26239+
// mark queue must be empty after process_mark_overflow
26240+
mark_queue.verify_empty();
2623926241

2624026242
// Perform the scan and set the flag if any promotions resulted.
2624126243
if (GCScan::GcDhReScan(sc))
@@ -26866,7 +26868,9 @@ void gc_heap::mark_phase (int condemned_gen_number, BOOL mark_only_p)
2686626868
// handle table has been fully promoted.
2686726869
GCScan::GcDhInitialScan(GCHeap::Promote, condemned_gen_number, max_generation, &sc);
2686826870
scan_dependent_handles(condemned_gen_number, &sc, true);
26869-
drain_mark_queue();
26871+
26872+
// mark queue must be empty after scan_dependent_handles
26873+
mark_queue.verify_empty();
2687026874
fire_mark_event (ETW::GC_ROOT_DH_HANDLES, current_promoted_bytes, last_promoted_bytes);
2687126875

2687226876
#ifdef MULTIPLE_HEAPS
@@ -26956,7 +26960,9 @@ void gc_heap::mark_phase (int condemned_gen_number, BOOL mark_only_p)
2695626960
// Scan dependent handles again to promote any secondaries associated with primaries that were promoted
2695726961
// for finalization. As before scan_dependent_handles will also process any mark stack overflow.
2695826962
scan_dependent_handles(condemned_gen_number, &sc, false);
26959-
drain_mark_queue();
26963+
26964+
// mark queue must be empty after scan_dependent_handles
26965+
mark_queue.verify_empty();
2696026966
fire_mark_event (ETW::GC_ROOT_DH_HANDLES, current_promoted_bytes, last_promoted_bytes);
2696126967
#endif //FEATURE_PREMORTEM_FINALIZATION
2696226968

0 commit comments

Comments
 (0)