mirror of
https://github.com/golang/go
synced 2024-09-29 15:14:28 -06:00
bdb480fd62
Currently, the statement: go g(uintptr(f())) gets rewritten into: tmp := f() newproc(8, g, uintptr(tmp)) runtime.KeepAlive(tmp) which doesn't guarantee that tmp is still alive by time the g call is scheduled to run. This CL fixes the issue, by wrapping g call in a closure: go func(p unsafe.Pointer) { g(uintptr(p)) }(f()) then this will be rewritten into: tmp := f() go func(p unsafe.Pointer) { g(uintptr(p)) runtime.KeepAlive(p) }(tmp) runtime.KeepAlive(tmp) // superfluous, but harmless So the unsafe.Pointer p will be kept alive at the time g call runs. Updates #24491 Change-Id: Ic10821251cbb1b0073daec92b82a866c6ebaf567 Reviewed-on: https://go-review.googlesource.com/c/go/+/253457 Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
46 lines
799 B
Go
46 lines
799 B
Go
// run
|
|
|
|
// Copyright 2020 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// This test makes sure unsafe-uintptr arguments are handled correctly.
|
|
|
|
package main
|
|
|
|
import (
|
|
"runtime"
|
|
"unsafe"
|
|
)
|
|
|
|
var done = make(chan bool, 1)
|
|
|
|
func setup() unsafe.Pointer {
|
|
s := "ok"
|
|
runtime.SetFinalizer(&s, func(p *string) { *p = "FAIL" })
|
|
return unsafe.Pointer(&s)
|
|
}
|
|
|
|
//go:noinline
|
|
//go:uintptrescapes
|
|
func test(s string, p uintptr) {
|
|
runtime.GC()
|
|
if *(*string)(unsafe.Pointer(p)) != "ok" {
|
|
panic(s + " return unexpected result")
|
|
}
|
|
done <- true
|
|
}
|
|
|
|
func main() {
|
|
test("normal", uintptr(setup()))
|
|
<-done
|
|
|
|
go test("go", uintptr(setup()))
|
|
<-done
|
|
|
|
func() {
|
|
defer test("defer", uintptr(setup()))
|
|
}()
|
|
<-done
|
|
}
|