Skip to content

Commit bb5bb24

Browse files
committed
gocore: skip nil largeType when discovering pointers
If a core is taken while a goroutine is allocating a large object (which is more likely than smaller objects, because zeroing is delayed and takes longer than for smaller objects) gocore might observe a nil largeType in the span, which is left nil to prevent the GC from trying to scan the partially-initialized object. Fixes golang/go#71182. Change-Id: Iafa7aed29466dc8ad6eac8f10171885421e10f76 Reviewed-on: https://go-review.googlesource.com/c/debug/+/641515 Reviewed-by: Nicolas Hillegeer <aktau@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
1 parent b341049 commit bb5bb24

File tree

1 file changed

+18
-10
lines changed

1 file changed

+18
-10
lines changed

internal/gocore/process.go

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,8 @@ func readHeap0(p *Process, mheap region, arenas []arena, arenaBaseOffset int64)
499499
continue
500500
}
501501
typeAddr := p.proc.ReadPtr(min.Add(off))
502+
// Note: typeAddr might be nil if the core was taken while a goroutine was
503+
// actively allocating a large object.
502504
if typeAddr == 0 {
503505
continue
504506
}
@@ -522,16 +524,22 @@ func readHeap0(p *Process, mheap region, arenas []arena, arenaBaseOffset int64)
522524
// is not valid if the object is dead. However, because large objects are
523525
// 1:1 with spans, we can be certain largeType is valid as long as the span
524526
// is in use.
525-
typ := s.Field("largeType").Deref()
526-
nptrs := int64(typ.Field("PtrBytes").Uintptr()) / int64(heap.ptrSize)
527-
kindGCProg, hasGCProgs := p.rtConsts.find("internal/abi.KindGCProg")
528-
if hasGCProgs && typ.Field("Kind_").Uint8()&uint8(kindGCProg) != 0 {
529-
panic("large object's GCProg was not unrolled")
530-
}
531-
gcdata := typ.Field("GCData").Address()
532-
for i := int64(0); i < nptrs; i++ {
533-
if p.proc.ReadUint8(gcdata.Add(i/8))>>uint(i%8)&1 != 0 {
534-
heap.setIsPointer(min.Add(i * int64(heap.ptrSize)))
527+
//
528+
// Note: largeType might be nil if the core was taken while a goroutine was
529+
// actively allocating a large object.
530+
typPtr := s.Field("largeType")
531+
if typPtr.Address() != 0 {
532+
typ := typPtr.Deref()
533+
nptrs := int64(typ.Field("PtrBytes").Uintptr()) / int64(heap.ptrSize)
534+
kindGCProg, hasGCProgs := p.rtConsts.find("internal/abi.KindGCProg")
535+
if hasGCProgs && typ.Field("Kind_").Uint8()&uint8(kindGCProg) != 0 {
536+
panic("large object's GCProg was not unrolled")
537+
}
538+
gcdata := typ.Field("GCData").Address()
539+
for i := int64(0); i < nptrs; i++ {
540+
if p.proc.ReadUint8(gcdata.Add(i/8))>>uint(i%8)&1 != 0 {
541+
heap.setIsPointer(min.Add(i * int64(heap.ptrSize)))
542+
}
535543
}
536544
}
537545
}

0 commit comments

Comments
 (0)