1// run
2
3// Copyright 2019 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// Issue 31419: race in getitab when two goroutines try
8// to do the same failed interface conversion.
9
10package main
11
12type T int
13
14func (t T) M() {}
15
16type I interface {
17	M()
18	M2()
19}
20
21var t T
22var e interface{} = &t
23var ok = false
24var ch = make(chan int)
25
26func main() {
27	_, ok = e.(I) // populate itab cache with a false result
28
29	go f() // get itab in a loop
30
31	var i I
32	for k := 0; k < 10000; k++ {
33		i, ok = e.(I) // read the cached itab
34		if ok {
35			println("iteration", k, "i =", i, "&t =", &t)
36			panic("conversion succeeded")
37		}
38	}
39	<-ch
40}
41
42func f() {
43	for i := 0; i < 10000; i++ {
44		f1()
45	}
46	ch <- 1
47}
48
49func f1() {
50	defer func() {
51		err := recover()
52		if err == nil {
53			panic("did not panic")
54		}
55	}()
56	i := e.(I) // triggers itab.init, for getting the panic string
57	_ = i
58}
59