blob: 868e926e66949a6c9a2e08f98d4b77b40601478c [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"
"io"
"os"
"runtime"
"runtime/pprof"
"sync"
)
func init() {
register("Etcd5509", Etcd5509)
}
var ErrConnClosed_etcd5509 error
type Client_etcd5509 struct {
mu sync.RWMutex
ctx context.Context
cancel context.CancelFunc
}
func (c *Client_etcd5509) Close() {
c.mu.Lock()
defer c.mu.Unlock()
if c.cancel == nil {
return
}
c.cancel()
c.cancel = nil
c.mu.Unlock()
c.mu.Lock()
}
type remoteClient_etcd5509 struct {
client *Client_etcd5509
mu sync.Mutex
}
func (r *remoteClient_etcd5509) acquire(ctx context.Context) error {
for {
r.client.mu.RLock()
closed := r.client.cancel == nil
r.mu.Lock()
r.mu.Unlock()
if closed {
return ErrConnClosed_etcd5509 // Missing RUnlock before return
}
r.client.mu.RUnlock()
}
}
type kv_etcd5509 struct {
rc *remoteClient_etcd5509
}
func (kv *kv_etcd5509) Get(ctx context.Context) error {
return kv.Do(ctx)
}
func (kv *kv_etcd5509) Do(ctx context.Context) error {
for {
err := kv.do(ctx)
if err == nil {
return nil
}
return err
}
}
func (kv *kv_etcd5509) do(ctx context.Context) error {
err := kv.getRemote(ctx)
return err
}
func (kv *kv_etcd5509) getRemote(ctx context.Context) error {
return kv.rc.acquire(ctx)
}
type KV interface {
Get(ctx context.Context) error
Do(ctx context.Context) error
}
func NewKV_etcd5509(c *Client_etcd5509) KV {
return &kv_etcd5509{rc: &remoteClient_etcd5509{
client: c,
}}
}
func Etcd5509() {
prof := pprof.Lookup("goroutineleak")
defer func() {
// Yield several times to allow the child goroutine to run.
for i := 0; i < yieldCount; i++ {
runtime.Gosched()
}
prof.WriteTo(os.Stdout, 2)
}()
go func() {
ctx, _ := context.WithCancel(context.TODO())
cli := &Client_etcd5509{
ctx: ctx,
}
kv := NewKV_etcd5509(cli)
donec := make(chan struct{})
go func() {
defer close(donec)
err := kv.Get(context.TODO())
if err != nil && err != ErrConnClosed_etcd5509 {
io.Discard.Write([]byte("Expect ErrConnClosed"))
}
}()
runtime.Gosched()
cli.Close()
<-donec
}()
}