mirror of
https://github.com/golang/go
synced 2024-09-04 23:44:16 +00:00
![Keith Randall](/assets/img/avatar_default.png)
Normally, reflect.makeFuncStub records the context value at a known point in the stack frame, so that the runtime can get the argument map for reflect.makeFuncStub from that known location. This doesn't work for defers or goroutines that haven't started yet, because they haven't allocated a frame or run an instruction yet. The argument map must be extracted from the context value. We already do this for defers (the non-nil ctxt arg to getArgInfo), we just need to do it for unstarted goroutines as well. When we traceback a goroutine, remember the context value from g.sched. Use it for the first frame we find. (We never need it for deeper frames, because we normally don't stop at the start of reflect.makeFuncStub, as it is nosplit. With this CL we could allow makeFuncStub to no longer be nosplit.) Fixes #25897 Change-Id: I427abf332a741a80728cdc0b8412aa8f37e7c418 Reviewed-on: https://go-review.googlesource.com/c/go/+/180258 Reviewed-by: Cherry Zhang <cherryyz@google.com>
39 lines
651 B
Go
39 lines
651 B
Go
// run
|
|
|
|
// Copyright 2019 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.
|
|
|
|
// Make sure the runtime can scan args of an unstarted goroutine
|
|
// which starts with a reflect-generated function.
|
|
|
|
package main
|
|
|
|
import (
|
|
"reflect"
|
|
"runtime"
|
|
)
|
|
|
|
const N = 100
|
|
|
|
type T struct {
|
|
}
|
|
|
|
func (t *T) Foo(c chan bool) {
|
|
c <- true
|
|
}
|
|
|
|
func main() {
|
|
t := &T{}
|
|
runtime.GOMAXPROCS(1)
|
|
c := make(chan bool, N)
|
|
for i := 0; i < N; i++ {
|
|
f := reflect.ValueOf(t).MethodByName("Foo").Interface().(func(chan bool))
|
|
go f(c)
|
|
}
|
|
runtime.GC()
|
|
for i := 0; i < N; i++ {
|
|
<-c
|
|
}
|
|
}
|