Source file src/runtime/testdata/testgoroutineleakprofile/goker/etcd7902.go

     1  // Copyright 2025 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a MIT
     3  // license that can be found in the LICENSE file.
     4  
     5  /*
     6   * Project: etcd
     7   * Issue or PR  : https://github.com/coreos/etcd/pull/7902
     8   * Buggy version: dfdaf082c51ba14861267f632f6af795a27eb4ef
     9   * fix commit-id: 87d99fe0387ee1df1cf1811d88d37331939ef4ae
    10   * Flaky: 100/100
    11   */
    12  package main
    13  
    14  import (
    15  	"os"
    16  	"runtime/pprof"
    17  	"sync"
    18  	"time"
    19  )
    20  
    21  func init() {
    22  	register("Etcd7902", Etcd7902)
    23  }
    24  
    25  type roundClient_etcd7902 struct {
    26  	progress int
    27  	acquire  func()
    28  	validate func()
    29  	release  func()
    30  }
    31  
    32  func runElectionFunc_etcd7902() {
    33  	rcs := make([]roundClient_etcd7902, 3)
    34  	nextc := make(chan bool)
    35  	for i := range rcs {
    36  		var rcNextc chan bool
    37  		setRcNextc := func() {
    38  			rcNextc = nextc
    39  		}
    40  		rcs[i].acquire = func() {}
    41  		rcs[i].validate = func() {
    42  			setRcNextc()
    43  		}
    44  		rcs[i].release = func() {
    45  			if i == 0 { // Assume the first roundClient is the leader
    46  				close(nextc)
    47  				nextc = make(chan bool)
    48  			}
    49  			<-rcNextc // Follower is blocking here
    50  		}
    51  	}
    52  	doRounds_etcd7902(rcs, 100)
    53  }
    54  
    55  func doRounds_etcd7902(rcs []roundClient_etcd7902, rounds int) {
    56  	var mu sync.Mutex
    57  	var wg sync.WaitGroup
    58  	wg.Add(len(rcs))
    59  	for i := range rcs {
    60  		go func(rc *roundClient_etcd7902) { // G2,G3
    61  			defer wg.Done()
    62  			for rc.progress < rounds || rounds <= 0 {
    63  				rc.acquire()
    64  				mu.Lock()
    65  				rc.validate()
    66  				mu.Unlock()
    67  				time.Sleep(10 * time.Millisecond)
    68  				rc.progress++
    69  				mu.Lock()
    70  				rc.release()
    71  				mu.Unlock()
    72  			}
    73  		}(&rcs[i])
    74  	}
    75  	wg.Wait()
    76  }
    77  
    78  func Etcd7902() {
    79  	prof := pprof.Lookup("goroutineleak")
    80  	defer func() {
    81  		time.Sleep(100 * time.Millisecond)
    82  		prof.WriteTo(os.Stdout, 2)
    83  	}()
    84  	for i := 0; i < 100; i++ {
    85  		go runElectionFunc_etcd7902() // G1
    86  	}
    87  }
    88  

View as plain text