Skip to content

Commit

Permalink
Fix issue dotnet#74741 - assert failure during weak pointer scanning. (
Browse files Browse the repository at this point in the history
…dotnet#74810)

The problem here is that during GCScan::GcWeakPtrScan, we call GCHeap::IsPromoted so we can zero out object pointers to objects that weren't marked. At the same time, one thread may do the same for the sync block table. When the first kind of threads validate the object, they also validate the sync block entry that may have already been zeroed - this causes an assert failure. I don't think there is any bad effect apart from the assert failure though.

The fix is to simply call Object::Validate with a bVerifySyncBlock of FALSE if the object hasn't been marked.
  • Loading branch information
PeterSolMS authored Aug 31, 2022
1 parent 104fe14 commit 9ac6c6d
Showing 1 changed file with 22 additions and 15 deletions.
37 changes: 22 additions & 15 deletions src/coreclr/gc/gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4473,8 +4473,12 @@ class CObjectHeader : public Object
return ((ArrayBase *)this)->GetNumComponents();
}

void Validate(BOOL bDeep=TRUE)
void Validate(BOOL bDeep=TRUE, BOOL bVerifyNextHeader = FALSE, BOOL bVerifySyncBlock = FALSE)
{
// declaration of extra parameters just so the call site would need no #ifdefs
UNREFERENCED_PARAMETER(bVerifyNextHeader);
UNREFERENCED_PARAMETER(bVerifySyncBlock);

MethodTable * pMT = GetMethodTable();

_ASSERTE(pMT->SanityCheck());
Expand Down Expand Up @@ -45145,15 +45149,10 @@ HRESULT GCHeap::Initialize()
// GC callback functions
bool GCHeap::IsPromoted(Object* object)
{
#ifdef _DEBUG
if (object)
{
((CObjectHeader*)object)->Validate();
}
#endif //_DEBUG

uint8_t* o = (uint8_t*)object;

bool is_marked;

if (gc_heap::settings.condemned_generation == max_generation)
{
#ifdef MULTIPLE_HEAPS
Expand All @@ -45165,27 +45164,35 @@ bool GCHeap::IsPromoted(Object* object)
#ifdef BACKGROUND_GC
if (gc_heap::settings.concurrent)
{
bool is_marked = (!((o < hp->background_saved_highest_address) && (o >= hp->background_saved_lowest_address))||
is_marked = (!((o < hp->background_saved_highest_address) && (o >= hp->background_saved_lowest_address))||
hp->background_marked (o));
return is_marked;
}
else
#endif //BACKGROUND_GC
{
return (!((o < hp->highest_address) && (o >= hp->lowest_address))
|| hp->is_mark_set (o));
is_marked = (!((o < hp->highest_address) && (o >= hp->lowest_address))
|| hp->is_mark_set (o));
}
}
else
{
#ifdef USE_REGIONS
return (gc_heap::is_in_gc_range (o) ? (gc_heap::is_in_condemned_gc (o) ? gc_heap::is_mark_set (o) : true) : true);
is_marked = (gc_heap::is_in_gc_range (o) ? (gc_heap::is_in_condemned_gc (o) ? gc_heap::is_mark_set (o) : true) : true);
#else
gc_heap* hp = gc_heap::heap_of (o);
return (!((o < hp->gc_high) && (o >= hp->gc_low))
|| hp->is_mark_set (o));
is_marked = (!((o < hp->gc_high) && (o >= hp->gc_low))
|| hp->is_mark_set (o));
#endif //USE_REGIONS
}

#ifdef _DEBUG
if (o)
{
((CObjectHeader*)o)->Validate(TRUE, TRUE, is_marked);
}
#endif //_DEBUG

return is_marked;
}

size_t GCHeap::GetPromotedBytes(int heap_index)
Expand Down

0 comments on commit 9ac6c6d

Please sign in to comment.