Source file src/runtime/testdata/testgoroutineleakprofile/goker/moby21233.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: moby
     7   * Issue or PR  : https://github.com/moby/moby/pull/21233
     8   * Buggy version: cc12d2bfaae135e63b1f962ad80e6943dd995337
     9   * fix commit-id: 2f4aa9658408ac72a598363c6e22eadf93dbb8a7
    10   * Flaky:100/100
    11   */
    12  package main
    13  
    14  import (
    15  	"math/rand"
    16  	"os"
    17  	"runtime/pprof"
    18  	"sync"
    19  	"time"
    20  )
    21  
    22  func init() {
    23  	register("Moby21233", Moby21233)
    24  }
    25  
    26  type Progress_moby21233 struct{}
    27  
    28  type Output_moby21233 interface {
    29  	WriteProgress(Progress_moby21233) error
    30  }
    31  
    32  type chanOutput_moby21233 chan<- Progress_moby21233
    33  
    34  type TransferManager_moby21233 struct {
    35  	mu sync.Mutex
    36  }
    37  
    38  type Transfer_moby21233 struct {
    39  	mu sync.Mutex
    40  }
    41  
    42  type Watcher_moby21233 struct {
    43  	signalChan  chan struct{}
    44  	releaseChan chan struct{}
    45  	running     chan struct{}
    46  }
    47  
    48  func ChanOutput_moby21233(progressChan chan<- Progress_moby21233) Output_moby21233 {
    49  	return chanOutput_moby21233(progressChan)
    50  }
    51  func (out chanOutput_moby21233) WriteProgress(p Progress_moby21233) error {
    52  	out <- p
    53  	return nil
    54  }
    55  func NewTransferManager_moby21233() *TransferManager_moby21233 {
    56  	return &TransferManager_moby21233{}
    57  }
    58  func NewTransfer_moby21233() *Transfer_moby21233 {
    59  	return &Transfer_moby21233{}
    60  }
    61  func (t *Transfer_moby21233) Release(watcher *Watcher_moby21233) {
    62  	t.mu.Lock()
    63  	t.mu.Unlock()
    64  	close(watcher.releaseChan)
    65  	<-watcher.running
    66  }
    67  func (t *Transfer_moby21233) Watch(progressOutput Output_moby21233) *Watcher_moby21233 {
    68  	t.mu.Lock()
    69  	defer t.mu.Unlock()
    70  	lastProgress := Progress_moby21233{}
    71  	w := &Watcher_moby21233{
    72  		releaseChan: make(chan struct{}),
    73  		signalChan:  make(chan struct{}),
    74  		running:     make(chan struct{}),
    75  	}
    76  	go func() { // G2
    77  		defer func() {
    78  			close(w.running)
    79  		}()
    80  		done := false
    81  		for {
    82  			t.mu.Lock()
    83  			t.mu.Unlock()
    84  			if rand.Int31n(2) >= 1 {
    85  				progressOutput.WriteProgress(lastProgress)
    86  			}
    87  			if done {
    88  				return
    89  			}
    90  			select {
    91  			case <-w.signalChan:
    92  			case <-w.releaseChan:
    93  				done = true
    94  			}
    95  		}
    96  	}()
    97  	return w
    98  }
    99  func (tm *TransferManager_moby21233) Transfer(progressOutput Output_moby21233) (*Transfer_moby21233, *Watcher_moby21233) {
   100  	tm.mu.Lock()
   101  	defer tm.mu.Unlock()
   102  	t := NewTransfer_moby21233()
   103  	return t, t.Watch(progressOutput)
   104  }
   105  
   106  func testTransfer_moby21233() { // G1
   107  	tm := NewTransferManager_moby21233()
   108  	progressChan := make(chan Progress_moby21233)
   109  	progressDone := make(chan struct{})
   110  	go func() { // G3
   111  		time.Sleep(1 * time.Millisecond)
   112  		for p := range progressChan { /// Chan consumer
   113  			if rand.Int31n(2) >= 1 {
   114  				return
   115  			}
   116  			_ = p
   117  		}
   118  		close(progressDone)
   119  	}()
   120  	time.Sleep(1 * time.Millisecond)
   121  	ids := []string{"id1", "id2", "id3"}
   122  	xrefs := make([]*Transfer_moby21233, len(ids))
   123  	watchers := make([]*Watcher_moby21233, len(ids))
   124  	for i := range ids {
   125  		xrefs[i], watchers[i] = tm.Transfer(ChanOutput_moby21233(progressChan)) /// Chan producer
   126  		time.Sleep(2 * time.Millisecond)
   127  	}
   128  
   129  	for i := range xrefs {
   130  		xrefs[i].Release(watchers[i])
   131  	}
   132  
   133  	close(progressChan)
   134  	<-progressDone
   135  }
   136  
   137  func Moby21233() {
   138  	prof := pprof.Lookup("goroutineleak")
   139  	defer func() {
   140  		time.Sleep(100 * time.Millisecond)
   141  		prof.WriteTo(os.Stdout, 2)
   142  	}()
   143  	for i := 0; i < 100; i++ {
   144  		go testTransfer_moby21233() // G1
   145  	}
   146  }
   147  

View as plain text