In
https://golang.org/issue/13347 , I raised a problem with
finalizers: if the finalizer of a value destroys some field of that
value, it's essential to ensure that the value is alive across any use
of that field. If the value becomes dead while the field is being
used, a GC might run, destroying the field and causing unpredictable
behavior. In cases involving C code, it might even lead to a program
crash.
Some existing Go programs today use finalizers incorrectly because of
this, and many are only correct because the compiler currently ensures
that all function arguments (and the receiver) are live for the extent
of the function. That compiler feature is undocumented and we don't
want to depend on it forever.
To address this problem, we (the Go runtime team) propose to add a new
function: runtime.KeepAlive. This function will take a single
argument and will simply ensure that its value is alive at that point
in the code. This may then be used in a function that uses a value
with a finalizer, to ensure that that value is alive for as long as is
necessary.
This is essentially what the syscall package does today, using an
unexported function syscall.use. It is also similar to what cgo does
today, using the unexported function runtime.cgoUse. Both those
functions could be replaced with runtime.KeepAlive.
The runtime.KeepAlive function is trivial:
//go:noinline
func KeepAlive(interface{}) {
}
Since this change is mainly documentation, we propose to do this for Go 1.7.
In future releases, the compiler may recognize the runtime.KeepAlive
function specially and implement it more efficiently, by simply
changing the liveness information recorded by the compiler. That
change will not be in 1.7 (and may never happen, who knows).
This approach is the same as that taken by C#:
https://msdn.microsoft.com/en-us/library/system.gc.keepalive(v=vs.110).aspx
.
Ian