Skip to content

cmd/compile: KeepAlive doesn't actually keep stack object alive #30476

@cherrymui

Description

@cherrymui

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

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions