// 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. package main import ( "fmt" "os" "runtime" "runtime/pprof" "sync" "time" ) func init() { register("Hugo3251", Hugo3251) } type remoteLock_hugo3251 struct { sync.RWMutex // L1 m map[string]*sync.Mutex // L2 } func (l *remoteLock_hugo3251) URLLock(url string) { l.Lock() // L1 if _, ok := l.m[url]; !ok { l.m[url] = &sync.Mutex{} } l.m[url].Lock() // L2 runtime.Gosched() l.Unlock() // L1 // runtime.Gosched() } func (l *remoteLock_hugo3251) URLUnlock(url string) { l.RLock() // L1 defer l.RUnlock() // L1 if um, ok := l.m[url]; ok { um.Unlock() // L2 } } func resGetRemote_hugo3251(remoteURLLock *remoteLock_hugo3251, url string) error { remoteURLLock.URLLock(url) defer func() { remoteURLLock.URLUnlock(url) }() return nil } func Hugo3251() { prof := pprof.Lookup("goroutineleak") defer func() { time.Sleep(time.Second) prof.WriteTo(os.Stdout, 2) }() for i := 0; i < 11; i++ { go func() { // G1 url := "http://Foo.Bar/foo_Bar-Foo" remoteURLLock := &remoteLock_hugo3251{m: make(map[string]*sync.Mutex)} for range []bool{false, true} { var wg sync.WaitGroup for i := 0; i < 100; i++ { wg.Add(1) go func(gor int) { // G2 defer wg.Done() for j := 0; j < 200; j++ { err := resGetRemote_hugo3251(remoteURLLock, url) if err != nil { fmt.Errorf("Error getting resource content: %s", err) } time.Sleep(300 * time.Nanosecond) } }(i) } wg.Wait() } }() } }