// 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. /* * Project: grpc-go * Issue or PR : https://github.com/grpc/grpc-go/pull/1424 * Buggy version: 39c8c3866d926d95e11c03508bf83d00f2963f91 * fix commit-id: 64bd0b04a7bb1982078bae6a2ab34c226125fbc1 * Flaky: 100/100 */ package main import ( "os" "runtime/pprof" "sync" "time" ) func init() { register("Grpc1424", Grpc1424) } type Balancer_grpc1424 interface { Notify() <-chan bool } type roundRobin_grpc1424 struct { mu sync.Mutex addrCh chan bool } func (rr *roundRobin_grpc1424) Notify() <-chan bool { return rr.addrCh } type addrConn_grpc1424 struct { mu sync.Mutex } func (ac *addrConn_grpc1424) tearDown() { ac.mu.Lock() defer ac.mu.Unlock() } type dialOption_grpc1424 struct { balancer Balancer_grpc1424 } type ClientConn_grpc1424 struct { dopts dialOption_grpc1424 conns []*addrConn_grpc1424 } func (cc *ClientConn_grpc1424) lbWatcher(doneChan chan bool) { for addr := range cc.dopts.balancer.Notify() { if addr { // nop, make compiler happy } var ( del []*addrConn_grpc1424 ) for _, a := range cc.conns { del = append(del, a) } for _, c := range del { c.tearDown() } } } func NewClientConn_grpc1424() *ClientConn_grpc1424 { cc := &ClientConn_grpc1424{ dopts: dialOption_grpc1424{ &roundRobin_grpc1424{addrCh: make(chan bool)}, }, } return cc } func DialContext_grpc1424() { cc := NewClientConn_grpc1424() waitC := make(chan error, 1) go func() { // G2 defer close(waitC) ch := cc.dopts.balancer.Notify() if ch != nil { doneChan := make(chan bool) go cc.lbWatcher(doneChan) // G3 <-doneChan } }() /// close addrCh close(cc.dopts.balancer.(*roundRobin_grpc1424).addrCh) } func Grpc1424() { prof := pprof.Lookup("goroutineleak") defer func() { time.Sleep(100 * time.Millisecond) prof.WriteTo(os.Stdout, 2) }() go DialContext_grpc1424() // G1 }