github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/zombie_collector.go (about) 1 package instrumentation 2 3 import ( 4 "context" 5 "github.com/Rookout/GoSDK/pkg/augs" 6 "github.com/Rookout/GoSDK/pkg/locations_set" 7 "github.com/Rookout/GoSDK/pkg/logger" 8 "github.com/Rookout/GoSDK/pkg/rookoutErrors" 9 "github.com/Rookout/GoSDK/pkg/utils" 10 "sync" 11 "time" 12 ) 13 14 type ClearBreakpointFunc func(*augs.Breakpoint) rookoutErrors.RookoutError 15 16 type ZombieCollector struct { 17 tickInterval time.Duration 18 readyTicker *time.Ticker 19 signalStop context.CancelFunc 20 stopCalled context.Context 21 sweeperFinished chan bool 22 locations *locations_set.LocationsSet 23 instrumentationLock sync.Locker 24 clearBreakpoint ClearBreakpointFunc 25 running bool 26 } 27 28 func NewZombieCollector(collectionInterval time.Duration, locations *locations_set.LocationsSet, instrumentationLock sync.Locker, clearBreakpoint ClearBreakpointFunc) *ZombieCollector { 29 30 return &ZombieCollector{ 31 tickInterval: collectionInterval, 32 locations: locations, 33 instrumentationLock: instrumentationLock, 34 clearBreakpoint: clearBreakpoint, 35 running: false, 36 } 37 } 38 39 40 41 func (z *ZombieCollector) Stop() { 42 if !z.running { 43 return 44 } 45 z.readyTicker.Stop() 46 z.signalStop() 47 <-z.sweeperFinished 48 z.running = false 49 } 50 51 52 53 54 func (z *ZombieCollector) Start() { 55 if z.running { 56 return 57 } 58 z.stopCalled, z.signalStop = context.WithCancel(context.Background()) 59 z.sweeperFinished = make(chan bool, 1) 60 z.readyTicker = time.NewTicker(z.tickInterval) 61 utils.CreateRetryingGoroutine(z.stopCalled, func() { 62 for { 63 select { 64 case <-z.stopCalled.Done(): 65 z.sweeperFinished <- true 66 return 67 case <-z.readyTicker.C: 68 z.clearStaleBreakpoints() 69 } 70 } 71 }) 72 z.running = true 73 } 74 75 func (z *ZombieCollector) clearStaleBreakpoints() { 76 z.instrumentationLock.Lock() 77 defer z.instrumentationLock.Unlock() 78 z.locations.Lock() 79 defer z.locations.Unlock() 80 staleBreakpoints := z.locations.GetBreakpointsToRemoveUnsafe() 81 for _, bp := range staleBreakpoints { 82 logger.Logger().Debugf("Trying to remove a stale breakpoint from %s:%d", bp.File, bp.Line) 83 if err := z.clearBreakpoint(bp); err != nil { 84 logger.Logger().WithError(err).Warningf("Failed removing stale breakpoint from %s:%d.", bp.File, bp.Line) 85 } else { 86 z.locations.RemoveBreakpointUnsafe(bp) 87 logger.Logger().Debugf("Removed a stale breakpoint from %s:%d", bp.File, bp.Line) 88 } 89 } 90 }