mirror of https://github.com/golang/go.git
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/1201 Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
508a22d5bc
commit
b796cbc406
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue