blob: aa8317c6d5f41bcf9015e607401eeb7435e1ae19 [file] [log] [blame]
// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
package main
import (
"context"
"os"
"runtime/pprof"
"sync"
"time"
)
func init() {
register("Istio17860", Istio17860)
}
type Proxy_istio17860 interface {
IsLive() bool
}
type TestProxy_istio17860 struct {
live func() bool
}
func (tp TestProxy_istio17860) IsLive() bool {
if tp.live == nil {
return true
}
return tp.live()
}
type Agent_istio17860 interface {
Run(ctx context.Context)
Restart()
}
type exitStatus_istio17860 int
type agent_istio17860 struct {
proxy Proxy_istio17860
mu *sync.Mutex
statusCh chan exitStatus_istio17860
currentEpoch int
activeEpochs map[int]struct{}
}
func (a *agent_istio17860) Run(ctx context.Context) {
for {
select {
case status := <-a.statusCh:
a.mu.Lock()
delete(a.activeEpochs, int(status))
active := len(a.activeEpochs)
a.mu.Unlock()
if active == 0 {
return
}
case <-ctx.Done():
return
}
}
}
func (a *agent_istio17860) Restart() {
a.mu.Lock()
defer a.mu.Unlock()
a.waitUntilLive()
a.currentEpoch++
a.activeEpochs[a.currentEpoch] = struct{}{}
go a.runWait(a.currentEpoch)
}
func (a *agent_istio17860) runWait(epoch int) {
a.statusCh <- exitStatus_istio17860(epoch)
}
func (a *agent_istio17860) waitUntilLive() {
if len(a.activeEpochs) == 0 {
return
}
interval := time.NewTicker(30 * time.Nanosecond)
timer := time.NewTimer(100 * time.Nanosecond)
defer func() {
interval.Stop()
timer.Stop()
}()
if a.proxy.IsLive() {
return
}
for {
select {
case <-timer.C:
return
case <-interval.C:
if a.proxy.IsLive() {
return
}
}
}
}
func NewAgent_istio17860(proxy Proxy_istio17860) Agent_istio17860 {
return &agent_istio17860{
proxy: proxy,
mu: &sync.Mutex{},
statusCh: make(chan exitStatus_istio17860),
activeEpochs: make(map[int]struct{}),
}
}
func Istio17860() {
prof := pprof.Lookup("goroutineleak")
defer func() {
time.Sleep(100 * time.Millisecond)
prof.WriteTo(os.Stdout, 2)
}()
for i := 0; i < 100; i++ {
go func() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
neverLive := func() bool {
return false
}
a := NewAgent_istio17860(TestProxy_istio17860{live: neverLive})
go func() { a.Run(ctx) }()
a.Restart()
go a.Restart()
time.Sleep(200 * time.Nanosecond)
}()
}
}