1
2
3
4
5 package race_test
6
7 import (
8 "runtime"
9 "sync"
10 "testing"
11 "time"
12 "unsafe"
13 )
14
15 func TestNoRaceFin(t *testing.T) {
16 c := make(chan bool)
17 go func() {
18 x := new(string)
19 runtime.SetFinalizer(x, func(x *string) {
20 *x = "foo"
21 })
22 *x = "bar"
23 c <- true
24 }()
25 <-c
26 runtime.GC()
27 time.Sleep(100 * time.Millisecond)
28 }
29
30 var finVar struct {
31 sync.Mutex
32 cnt int
33 }
34
35 func TestNoRaceFinGlobal(t *testing.T) {
36 c := make(chan bool)
37 go func() {
38 x := new(string)
39 runtime.SetFinalizer(x, func(x *string) {
40 finVar.Lock()
41 finVar.cnt++
42 finVar.Unlock()
43 })
44 c <- true
45 }()
46 <-c
47 runtime.GC()
48 time.Sleep(100 * time.Millisecond)
49 finVar.Lock()
50 finVar.cnt++
51 finVar.Unlock()
52 }
53
54 func TestRaceFin(t *testing.T) {
55 c := make(chan bool)
56 y := 0
57 _ = y
58 go func() {
59 x := new(string)
60 runtime.SetFinalizer(x, func(x *string) {
61 y = 42
62 })
63 c <- true
64 }()
65 <-c
66 runtime.GC()
67 time.Sleep(100 * time.Millisecond)
68 y = 66
69 }
70
71 func TestNoRaceCleanup(t *testing.T) {
72 c := make(chan bool)
73 go func() {
74 x := new(string)
75 y := new(string)
76 runtime.AddCleanup(x, func(y *string) {
77 *y = "foo"
78 }, y)
79 *y = "bar"
80 runtime.KeepAlive(x)
81 c <- true
82 }()
83 <-c
84 runtime.GC()
85 time.Sleep(100 * time.Millisecond)
86 }
87
88 func TestRaceBetweenCleanups(t *testing.T) {
89
90
91
92 type T struct {
93 v int
94 p unsafe.Pointer
95 }
96 sharedVar := new(int)
97 v0 := new(T)
98 v1 := new(T)
99 cleanup := func(x int) {
100 *sharedVar = x
101 }
102 runtime.AddCleanup(v0, cleanup, 0)
103 runtime.AddCleanup(v1, cleanup, 0)
104 v0 = nil
105 v1 = nil
106
107 runtime.GC()
108 time.Sleep(100 * time.Millisecond)
109 }
110
View as plain text