runtime: update docs, code for SetFinalizer
At last minute before 1.3 we relaxed SetFinalizer to avoid
crashes when you pass the result of a global alloc to it.
This avoids the crash but makes SetFinalizer a bit too relaxed.
Document that the finalizer of a global allocation may not run.
Tighten the SetFinalizer check to ignore a global allocation but
not ignore everything else.
Fixes #7656.
LGTM=r, iant
R=golang-codereviews, iant, r
CC=dvyukov, golang-codereviews, khr, rlh
https://golang.org/cl/145930043
diff --git a/src/runtime/mfinal_test.go b/src/runtime/mfinal_test.go
index 6b53888..d2cead2 100644
--- a/src/runtime/mfinal_test.go
+++ b/src/runtime/mfinal_test.go
@@ -44,10 +44,17 @@
{func(x *int) interface{} { return (*Tint)(x) }, func(v Tinter) { finalize((*int)(v.(*Tint))) }},
}
- for _, tt := range finalizerTests {
+ for i, tt := range finalizerTests {
done := make(chan bool, 1)
go func() {
- v := new(int)
+ // allocate struct with pointer to avoid hitting tinyalloc.
+ // Otherwise we can't be sure when the allocation will
+ // be freed.
+ type T struct {
+ v int
+ p unsafe.Pointer
+ }
+ v := &new(T).v
*v = 97531
runtime.SetFinalizer(tt.convert(v), tt.finalizer)
v = nil
@@ -58,7 +65,7 @@
select {
case <-ch:
case <-time.After(time.Second * 4):
- t.Errorf("finalizer for type %T didn't run", tt.finalizer)
+ t.Errorf("#%d: finalizer for type %T didn't run", i, tt.finalizer)
}
}
}