chore: delete unused code that doesn't build on Windows (#22443)

pull/22454/head
Daniel Moran 2021-09-13 10:55:45 -04:00 committed by GitHub
parent 1e911cdba6
commit 372c481278
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 0 additions and 257 deletions

View File

@ -1,104 +0,0 @@
package lifecycle
import "sync"
// Resource keeps track of references and has some compile time debug hooks
// to help diagnose leaks. It keeps track of if it is open or not and allows
// blocking until all references are released.
type Resource struct {
stmu sync.Mutex // protects state transitions
chmu sync.RWMutex // protects channel mutations
ch chan struct{} // signals references to close
wg sync.WaitGroup // counts outstanding references
}
// Open marks the resource as open.
func (res *Resource) Open() {
res.stmu.Lock()
defer res.stmu.Unlock()
res.chmu.Lock()
res.ch = make(chan struct{})
res.chmu.Unlock()
}
// Close waits for any outstanding references and marks the resource as closed
// so that Acquire returns an error.
func (res *Resource) Close() {
res.stmu.Lock()
defer res.stmu.Unlock()
res.chmu.Lock()
if res.ch != nil {
close(res.ch) // signal any references.
res.ch = nil // stop future Acquires
}
res.chmu.Unlock()
res.wg.Wait() // wait for any acquired references
}
// Opened returns true if the resource is currently open. It may be immediately
// false in the presence of concurrent Open and Close calls.
func (res *Resource) Opened() bool {
res.chmu.RLock()
opened := res.ch != nil
res.chmu.RUnlock()
return opened
}
// Acquire returns a Reference used to keep alive some resource.
func (res *Resource) Acquire() (*Reference, error) {
res.chmu.RLock()
defer res.chmu.RUnlock()
ch := res.ch
if ch == nil {
return nil, resourceClosed()
}
res.wg.Add(1)
return live.track(&Reference{wg: &res.wg, ch: ch}), nil
}
// Reference is an open reference for some resource.
type Reference struct {
once sync.Once
wg *sync.WaitGroup
ch <-chan struct{}
id uint64
}
// Closing returns a channel that will be closed when the associated resource begins closing.
func (ref *Reference) Closing() <-chan struct{} { return ref.ch }
// Release causes the Reference to be freed. It is safe to call multiple times.
func (ref *Reference) Release() {
ref.once.Do(func() {
live.untrack(ref)
ref.wg.Done()
})
}
// Close makes a Reference an io.Closer. It is safe to call multiple times.
func (ref *Reference) Close() error {
ref.Release()
return nil
}
// References is a helper to aggregate a group of references.
type References []*Reference
// Release releases all of the references. It is safe to call multiple times.
func (refs References) Release() {
for _, ref := range refs {
ref.Release()
}
}
// Close makes References an io.Closer. It is safe to call multiple times.
func (refs References) Close() error {
refs.Release()
return nil
}

View File

@ -1,139 +0,0 @@
package lifecycle
import (
"errors"
"fmt"
"io"
"os"
"os/signal"
"path/filepath"
"runtime"
"sync"
"syscall"
)
var resourceDebugEnabled = os.Getenv("INFLUXDB_EXP_RESOURCE_DEBUG") != ""
// When in debug mode, we associate each reference an id and with that id the
// stack trace that created it. We can't directly refer to the reference here
// because we also associate a finalizer to print to stderr if a reference is
// leaked, including where it came from if possible.
func init() {
if !resourceDebugEnabled {
return
}
// This goroutine will dump all live references and where they were created
// when SIGUSR2 is sent to the process.
go func() {
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGUSR2)
for range ch {
live.mu.Lock()
for id, pcs := range live.live {
fmt.Fprintln(os.Stderr, "=====================================================")
fmt.Fprintln(os.Stderr, "=== Live reference with id", id, "created from")
summarizeStack(os.Stderr, pcs)
fmt.Fprintln(os.Stderr, "=====================================================")
}
live.mu.Unlock()
}
}()
}
// resourceClosed returns an error stating that some resource is closed with the
// stack trace of the caller embedded.
func resourceClosed() error {
if !resourceDebugEnabled {
return errors.New("resource closed")
}
var buf [4096]byte
return fmt.Errorf("resource closed:\n%s", buf[:runtime.Stack(buf[:], false)])
}
// liveReferences keeps track of the stack traces of all of the live references.
type liveReferences struct {
mu sync.Mutex
id uint64
live map[uint64][]uintptr
}
var live = &liveReferences{
live: make(map[uint64][]uintptr),
}
// finishId informs the liveReferences that the id is no longer in use.
func (l *liveReferences) untrack(r *Reference) {
if !resourceDebugEnabled {
return
}
l.mu.Lock()
delete(l.live, r.id)
runtime.SetFinalizer(r, nil)
l.mu.Unlock()
}
// withFinalizer associates a finalizer with the Reference that will cause it
// to print a leak message if it is not closed before it is garbage collected.
func (l *liveReferences) track(r *Reference) *Reference {
if !resourceDebugEnabled {
return r
}
var buf [32]uintptr
pcs := append([]uintptr(nil), buf[:runtime.Callers(3, buf[:])]...)
l.mu.Lock()
r.id, l.id = l.id, l.id+1
l.live[r.id] = pcs
l.mu.Unlock()
runtime.SetFinalizer(r, func(r *Reference) {
l.leaked(r)
r.Release()
})
return r
}
// leaked prints a loud message on stderr that the Reference was leaked and
// what was responsible for calling it.
func (l *liveReferences) leaked(r *Reference) {
if !resourceDebugEnabled {
return
}
l.mu.Lock()
pcs, ok := l.live[r.id]
l.mu.Unlock()
if !ok {
fmt.Fprintln(os.Stderr, "=====================================================")
fmt.Fprintln(os.Stderr, "=== Leaked a reference with no stack associated!? ===")
fmt.Fprintln(os.Stderr, "=====================================================")
return
}
fmt.Fprintln(os.Stderr, "=====================================================")
fmt.Fprintln(os.Stderr, "=== Leaked a reference! Created from")
summarizeStack(os.Stderr, pcs)
fmt.Fprintln(os.Stderr, "=====================================================")
}
// summarizeStack prints a line for each stack entry in the pcs to the writer.
func summarizeStack(w io.Writer, pcs []uintptr) {
frames := runtime.CallersFrames(pcs)
for {
frame, more := frames.Next()
if !more {
break
}
fmt.Fprintf(w, " %s:%s:%d\n",
frame.Function,
filepath.Base(frame.File),
frame.Line)
}
}

View File

@ -1,14 +0,0 @@
package lifecycle
import (
"runtime"
"testing"
)
// TestReferenceLeak is only useful to test printing with the debug build tag.
func TestReferenceLeak(t *testing.T) {
var res Resource
res.Open()
res.Acquire()
runtime.GC()
}