Source file src/runtime/testdata/testgoroutineleakprofile/goker/etcd6873.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/etcd-io/etcd/commit/7618fdd1d642e47cac70c03f637b0fd798a53a6e
     8   * Buggy version: 377f19b0031f9c0aafe2aec28b6f9019311f52f9
     9   * fix commit-id: 7618fdd1d642e47cac70c03f637b0fd798a53a6e
    10   * Flaky: 9/100
    11   */
    12  package main
    13  
    14  import (
    15  	"os"
    16  	"runtime/pprof"
    17  	"sync"
    18  	"time"
    19  )
    20  
    21  func init() {
    22  	register("Etcd6873", Etcd6873)
    23  }
    24  
    25  type watchBroadcast_etcd6873 struct{}
    26  
    27  type watchBroadcasts_etcd6873 struct {
    28  	mu      sync.Mutex
    29  	updatec chan *watchBroadcast_etcd6873
    30  	donec   chan struct{}
    31  }
    32  
    33  func newWatchBroadcasts_etcd6873() *watchBroadcasts_etcd6873 {
    34  	wbs := &watchBroadcasts_etcd6873{
    35  		updatec: make(chan *watchBroadcast_etcd6873, 1),
    36  		donec:   make(chan struct{}),
    37  	}
    38  	go func() { // G2
    39  		defer close(wbs.donec)
    40  		for wb := range wbs.updatec {
    41  			wbs.coalesce(wb)
    42  		}
    43  	}()
    44  	return wbs
    45  }
    46  
    47  func (wbs *watchBroadcasts_etcd6873) coalesce(wb *watchBroadcast_etcd6873) {
    48  	wbs.mu.Lock()
    49  	wbs.mu.Unlock()
    50  }
    51  
    52  func (wbs *watchBroadcasts_etcd6873) stop() {
    53  	wbs.mu.Lock()
    54  	defer wbs.mu.Unlock()
    55  	close(wbs.updatec)
    56  	<-wbs.donec
    57  }
    58  
    59  func (wbs *watchBroadcasts_etcd6873) update(wb *watchBroadcast_etcd6873) {
    60  	select {
    61  	case wbs.updatec <- wb:
    62  	default:
    63  	}
    64  }
    65  
    66  // Example of goroutine leak trace:
    67  //
    68  // G1                   G2                  G3
    69  //---------------------------------------------------------
    70  // newWatchBroadcasts()
    71  //	wbs.update()
    72  // wbs.updatec <-
    73  // return
    74  //                      <-wbs.updatec
    75  //                      wbs.coalesce()
    76  //                                         wbs.stop()
    77  //                                         wbs.mu.Lock()
    78  //                                         close(wbs.updatec)
    79  //                                         <-wbs.donec
    80  //                      wbs.mu.Lock()
    81  //---------------------G2,G3 leak-------------------------
    82  //
    83  
    84  func Etcd6873() {
    85  	prof := pprof.Lookup("goroutineleak")
    86  	defer func() {
    87  		time.Sleep(100 * time.Millisecond)
    88  		prof.WriteTo(os.Stdout, 2)
    89  	}()
    90  
    91  	for i := 0; i < 100; i++ {
    92  		go func() {
    93  			wbs := newWatchBroadcasts_etcd6873() // G1
    94  			wbs.update(&watchBroadcast_etcd6873{})
    95  			go wbs.stop() // G3
    96  		}()
    97  	}
    98  }
    99  

View as plain text