1
2
3
4
5 package main
6
7 import (
8 "context"
9 "os"
10 "runtime/pprof"
11
12 "sync"
13 "time"
14 )
15
16 func init() {
17 register("Istio17860", Istio17860)
18 }
19
20 type Proxy_istio17860 interface {
21 IsLive() bool
22 }
23
24 type TestProxy_istio17860 struct {
25 live func() bool
26 }
27
28 func (tp TestProxy_istio17860) IsLive() bool {
29 if tp.live == nil {
30 return true
31 }
32 return tp.live()
33 }
34
35 type Agent_istio17860 interface {
36 Run(ctx context.Context)
37 Restart()
38 }
39
40 type exitStatus_istio17860 int
41
42 type agent_istio17860 struct {
43 proxy Proxy_istio17860
44 mu *sync.Mutex
45 statusCh chan exitStatus_istio17860
46 currentEpoch int
47 activeEpochs map[int]struct{}
48 }
49
50 func (a *agent_istio17860) Run(ctx context.Context) {
51 for {
52 select {
53 case status := <-a.statusCh:
54 a.mu.Lock()
55 delete(a.activeEpochs, int(status))
56 active := len(a.activeEpochs)
57 a.mu.Unlock()
58 if active == 0 {
59 return
60 }
61 case <-ctx.Done():
62 return
63 }
64 }
65 }
66
67 func (a *agent_istio17860) Restart() {
68 a.mu.Lock()
69 defer a.mu.Unlock()
70
71 a.waitUntilLive()
72 a.currentEpoch++
73 a.activeEpochs[a.currentEpoch] = struct{}{}
74
75 go a.runWait(a.currentEpoch)
76 }
77
78 func (a *agent_istio17860) runWait(epoch int) {
79 a.statusCh <- exitStatus_istio17860(epoch)
80 }
81
82 func (a *agent_istio17860) waitUntilLive() {
83 if len(a.activeEpochs) == 0 {
84 return
85 }
86
87 interval := time.NewTicker(30 * time.Nanosecond)
88 timer := time.NewTimer(100 * time.Nanosecond)
89 defer func() {
90 interval.Stop()
91 timer.Stop()
92 }()
93
94 if a.proxy.IsLive() {
95 return
96 }
97
98 for {
99 select {
100 case <-timer.C:
101 return
102 case <-interval.C:
103 if a.proxy.IsLive() {
104 return
105 }
106 }
107 }
108 }
109
110 func NewAgent_istio17860(proxy Proxy_istio17860) Agent_istio17860 {
111 return &agent_istio17860{
112 proxy: proxy,
113 mu: &sync.Mutex{},
114 statusCh: make(chan exitStatus_istio17860),
115 activeEpochs: make(map[int]struct{}),
116 }
117 }
118
119 func Istio17860() {
120 prof := pprof.Lookup("goroutineleak")
121 defer func() {
122 time.Sleep(100 * time.Millisecond)
123 prof.WriteTo(os.Stdout, 2)
124 }()
125
126 for i := 0; i < 100; i++ {
127 go func() {
128 ctx, cancel := context.WithCancel(context.Background())
129 defer cancel()
130
131 neverLive := func() bool {
132 return false
133 }
134
135 a := NewAgent_istio17860(TestProxy_istio17860{live: neverLive})
136 go func() { a.Run(ctx) }()
137
138 a.Restart()
139 go a.Restart()
140
141 time.Sleep(200 * time.Nanosecond)
142 }()
143 }
144 }
145
View as plain text