mirror of
https://github.com/golang/go
synced 2024-11-19 13:04:45 -07:00
runtime: add a use of runtime.KeepAlive's argument
This makes sure that its argument is marked live on entry. We need its arg to be live so defers of KeepAlive get scanned correctly by the GC. Fixes #21402 Change-Id: I906813e433d0e9726ca46483723303338da5b4d7 Reviewed-on: https://go-review.googlesource.com/55150 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
1f631a2f9a
commit
2c990f4596
@ -461,11 +461,7 @@ func findObject(v unsafe.Pointer) (s *mspan, x unsafe.Pointer, n uintptr) {
|
||||
return
|
||||
}
|
||||
|
||||
// Mark KeepAlive as noinline so that the current compiler will ensure
|
||||
// that the argument is alive at the point of the function call.
|
||||
// If it were inlined, it would disappear, and there would be nothing
|
||||
// keeping the argument alive. Perhaps a future compiler will recognize
|
||||
// runtime.KeepAlive specially and do something more efficient.
|
||||
// Mark KeepAlive as noinline so that it is easily detectable as an intrinsic.
|
||||
//go:noinline
|
||||
|
||||
// KeepAlive marks its argument as currently reachable.
|
||||
@ -487,4 +483,11 @@ func findObject(v unsafe.Pointer) (s *mspan, x unsafe.Pointer, n uintptr) {
|
||||
// Without the KeepAlive call, the finalizer could run at the start of
|
||||
// syscall.Read, closing the file descriptor before syscall.Read makes
|
||||
// the actual system call.
|
||||
func KeepAlive(interface{}) {}
|
||||
func KeepAlive(x interface{}) {
|
||||
// Introduce a use of x that the compiler can't eliminate.
|
||||
// This makes sure x is alive on entry. We need x to be alive
|
||||
// on entry for "defer runtime.KeepAlive(x)"; see issue 21402.
|
||||
if cgoAlwaysFalse {
|
||||
println(x)
|
||||
}
|
||||
}
|
||||
|
@ -241,3 +241,20 @@ var (
|
||||
Foo2 = &Object2{}
|
||||
Foo1 = &Object1{}
|
||||
)
|
||||
|
||||
func TestDeferKeepAlive(t *testing.T) {
|
||||
// See issue 21402.
|
||||
t.Parallel()
|
||||
type T *int // needs to be a pointer base type to avoid tinyalloc and its never-finalized behavior.
|
||||
x := new(T)
|
||||
finRun := false
|
||||
runtime.SetFinalizer(x, func(x *T) {
|
||||
finRun = true
|
||||
})
|
||||
defer runtime.KeepAlive(x)
|
||||
runtime.GC()
|
||||
time.Sleep(time.Second)
|
||||
if finRun {
|
||||
t.Errorf("finalizer ran prematurely")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user