blob: 1846d0f260c2f6165e2e1675e2524fd31349529e [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.
/*
* Project: etcd
* Issue or PR : https://github.com/etcd-io/etcd/commit/7618fdd1d642e47cac70c03f637b0fd798a53a6e
* Buggy version: 377f19b0031f9c0aafe2aec28b6f9019311f52f9
* fix commit-id: 7618fdd1d642e47cac70c03f637b0fd798a53a6e
* Flaky: 9/100
*/
package main
import (
"os"
"runtime/pprof"
"sync"
"time"
)
func init() {
register("Etcd6873", Etcd6873)
}
type watchBroadcast_etcd6873 struct{}
type watchBroadcasts_etcd6873 struct {
mu sync.Mutex
updatec chan *watchBroadcast_etcd6873
donec chan struct{}
}
func newWatchBroadcasts_etcd6873() *watchBroadcasts_etcd6873 {
wbs := &watchBroadcasts_etcd6873{
updatec: make(chan *watchBroadcast_etcd6873, 1),
donec: make(chan struct{}),
}
go func() { // G2
defer close(wbs.donec)
for wb := range wbs.updatec {
wbs.coalesce(wb)
}
}()
return wbs
}
func (wbs *watchBroadcasts_etcd6873) coalesce(wb *watchBroadcast_etcd6873) {
wbs.mu.Lock()
wbs.mu.Unlock()
}
func (wbs *watchBroadcasts_etcd6873) stop() {
wbs.mu.Lock()
defer wbs.mu.Unlock()
close(wbs.updatec)
<-wbs.donec
}
func (wbs *watchBroadcasts_etcd6873) update(wb *watchBroadcast_etcd6873) {
select {
case wbs.updatec <- wb:
default:
}
}
// Example of goroutine leak trace:
//
// G1 G2 G3
//---------------------------------------------------------
// newWatchBroadcasts()
// wbs.update()
// wbs.updatec <-
// return
// <-wbs.updatec
// wbs.coalesce()
// wbs.stop()
// wbs.mu.Lock()
// close(wbs.updatec)
// <-wbs.donec
// wbs.mu.Lock()
//---------------------G2,G3 leak-------------------------
//
func Etcd6873() {
prof := pprof.Lookup("goroutineleak")
defer func() {
time.Sleep(100 * time.Millisecond)
prof.WriteTo(os.Stdout, 2)
}()
for i := 0; i < 100; i++ {
go func() {
wbs := newWatchBroadcasts_etcd6873() // G1
wbs.update(&watchBroadcast_etcd6873{})
go wbs.stop() // G3
}()
}
}