1// run 2 3// Copyright 2018 The Go Authors. All rights reserved. 4// Use of this source code is governed by a BSD-style 5// license that can be found in the LICENSE file. 6 7// Make sure return values are always scanned, when 8// calling methods (+functions, TODO) with reflect. 9 10package main 11 12import ( 13 "reflect" 14 "runtime/debug" 15 "sync" 16) 17 18func main() { 19 debug.SetGCPercent(1) // run GC frequently 20 var wg sync.WaitGroup 21 for i := 0; i < 20; i++ { 22 wg.Add(1) 23 go func() { 24 defer wg.Done() 25 for i := 0; i < 2000; i++ { 26 _test() 27 } 28 }() 29 } 30 wg.Wait() 31} 32 33type Stt struct { 34 Data interface{} 35} 36 37type My struct { 38 b byte 39} 40 41func (this *My) Run(rawData []byte) (Stt, error) { 42 var data string = "hello" 43 stt := Stt{ 44 Data: data, 45 } 46 return stt, nil 47} 48 49func _test() (interface{}, error) { 50 f := reflect.ValueOf(&My{}).MethodByName("Run") 51 if method, ok := f.Interface().(func([]byte) (Stt, error)); ok { 52 s, e := method(nil) 53 // The bug in issue27695 happens here, during the return 54 // from the above call (at the end of reflect.callMethod 55 // when preparing to return). The result value that 56 // is assigned to s was not being scanned if GC happens 57 // to occur there. 58 i := interface{}(s) 59 return i, e 60 } 61 return nil, nil 62} 63