Commit b796cbc4 authored by Keith Randall's avatar Keith Randall

runtime: fix finalizer iterator

It could only handle one finalizer before it raised an out-of-bounds error.

Fixes issue #9172

Change-Id: Ibb4d0c8aff2d78a1396e248c7129a631176ab427
Reviewed-on: https://go-review.googlesource.com/1201Reviewed-by: default avatarRuss Cox <rsc@golang.org>
parent 508a22d5
......@@ -31,3 +31,40 @@ func TestWriteHeapDumpNonempty(t *testing.T) {
t.Fatalf("Heap dump size %d bytes, expected at least %d bytes", size, minSize)
}
}
type Obj struct {
x, y int
}
func objfin(x *Obj) {
println("finalized", x)
}
func TestWriteHeapDumpFinalizers(t *testing.T) {
if runtime.GOOS == "nacl" {
t.Skip("WriteHeapDump is not available on NaCl.")
}
f, err := ioutil.TempFile("", "heapdumptest")
if err != nil {
t.Fatalf("TempFile failed: %v", err)
}
defer os.Remove(f.Name())
defer f.Close()
// bug 9172: WriteHeapDump couldn't handle more than one finalizer
println("allocating objects")
x := &Obj{}
runtime.SetFinalizer(x, objfin)
y := &Obj{}
runtime.SetFinalizer(y, objfin)
// Trigger collection of x and y, queueing of their finalizers.
println("starting gc")
runtime.GC()
// Make sure WriteHeapDump doesn't fail with multiple queued finalizers.
println("starting dump")
WriteHeapDump(f.Fd())
println("done dump")
}
......@@ -476,8 +476,8 @@ type finblock struct {
alllink *finblock
next *finblock
cnt int32
cap int32
fin [1]finalizer
_ int32
fin [(_FinBlockSize-2*ptrSize-2*4)/unsafe.Sizeof(finalizer{})]finalizer
}
// Information from the compiler about the layout of stack frames.
......
......@@ -1093,10 +1093,9 @@ var finalizer1 = [...]byte{
func queuefinalizer(p unsafe.Pointer, fn *funcval, nret uintptr, fint *_type, ot *ptrtype) {
lock(&finlock)
if finq == nil || finq.cnt == finq.cap {
if finq == nil || finq.cnt == int32(len(finq.fin)) {
if finc == nil {
finc = (*finblock)(persistentalloc(_FinBlockSize, 0, &memstats.gc_sys))
finc.cap = int32((_FinBlockSize-unsafe.Sizeof(finblock{}))/unsafe.Sizeof(finalizer{}) + 1)
finc.alllink = allfin
allfin = finc
if finptrmask[0] == 0 {
......@@ -1121,7 +1120,7 @@ func queuefinalizer(p unsafe.Pointer, fn *funcval, nret uintptr, fint *_type, ot
block.next = finq
finq = block
}
f := (*finalizer)(add(unsafe.Pointer(&finq.fin[0]), uintptr(finq.cnt)*unsafe.Sizeof(finq.fin[0])))
f := &finq.fin[finq.cnt]
finq.cnt++
f.fn = fn
f.nret = nret
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment