-
Notifications
You must be signed in to change notification settings - Fork 18.3k
Closed
Labels
FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.The path to resolution is known, but the work has not been done.release-blocker
Milestone
Description
What version of Go are you using (go version
)?
tip (62f5e81)
Does this issue reproduce with the latest release?
Yes with Go 1.12. No with Go 1.11.
What operating system and processor architecture are you using (go env
)?
darwin/amd64
What did you do?
package main
import "runtime"
var c = make(chan int)
func main() {
x := new([10]int)
runtime.SetFinalizer(x, func(*[10]int){ println("finalizer runs"); c <- 0 })
p := &T{x, 0} // T{x, 0} is allocated on stack
use(p)
runtime.GC()
runtime.GC()
runtime.GC()
runtime.KeepAlive(p)
<-c
}
type T struct { x *[10]int; y int }
//go:noinline
func use(*T) {}
(no playground link as the playground seems down...)
What did you expect to see?
KeepAlive(p)
keeps p alive, which in turn keeps x alive, so the finalizer does not run, and the program deadlocks.
This is the behavior with Go 1.11.
$ go1.11 run keepalive2.go
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
/tmp/keepalive2.go:16 +0xb4
exit status 2
This is also the behavior if we use a dummy use call to keep p alive (i.e. the equivalent of the non-intrinsic runtime.KeepAlive).
What did you see instead?
Finalizer runs.
$ go-tip run keepalive2.go
finalizer runs
This is because the address of the stack object is rematerializeable, and the compiler just ignores KeepAlive on rematerializeable values. I'll send a CL.
Metadata
Metadata
Assignees
Labels
FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.The path to resolution is known, but the work has not been done.release-blocker