| // run | |
| // Copyright 2018 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 return values are always scanned, when | |
| // calling methods (+functions, TODO) with reflect. | |
| package main | |
| import ( | |
| "reflect" | |
| "runtime/debug" | |
| "sync" | |
| ) | |
| func main() { | |
| debug.SetGCPercent(1) // run GC frequently | |
| var wg sync.WaitGroup | |
| for i := 0; i < 20; i++ { | |
| wg.Add(1) | |
| go func() { | |
| defer wg.Done() | |
| for i := 0; i < 2000; i++ { | |
| _test() | |
| } | |
| }() | |
| } | |
| wg.Wait() | |
| } | |
| type Stt struct { | |
| Data interface{} | |
| } | |
| type My struct { | |
| b byte | |
| } | |
| func (this *My) Run(rawData []byte) (Stt, error) { | |
| var data string = "hello" | |
| stt := Stt{ | |
| Data: data, | |
| } | |
| return stt, nil | |
| } | |
| func _test() (interface{}, error) { | |
| f := reflect.ValueOf(&My{}).MethodByName("Run") | |
| if method, ok := f.Interface().(func([]byte) (Stt, error)); ok { | |
| s, e := method(nil) | |
| // The bug in issue27695 happens here, during the return | |
| // from the above call (at the end of reflect.callMethod | |
| // when preparing to return). The result value that | |
| // is assigned to s was not being scanned if GC happens | |
| // to occur there. | |
| i := interface{}(s) | |
| return i, e | |
| } | |
| return nil, nil | |
| } |