swarm: fix uptime gauge update goroutine leak by introducing cleanup functions (#19040)

This commit is contained in:
Elad 2019-02-13 14:15:03 +07:00 committed by Viktor Trón
parent 555b3652dc
commit d596bea2d5

View File

@ -79,7 +79,7 @@ type Swarm struct {
swap *swap.Swap
stateStore *state.DBStore
accountingMetrics *protocols.AccountingMetrics
startTime time.Time
cleanupFuncs []func() error
tracerClose io.Closer
}
@ -106,9 +106,10 @@ func NewSwarm(config *api.Config, mockStore *mock.NodeStore) (self *Swarm, err e
}
self = &Swarm{
config: config,
backend: backend,
privateKey: config.ShiftPrivateKey(),
config: config,
backend: backend,
privateKey: config.ShiftPrivateKey(),
cleanupFuncs: []func() error{},
}
log.Debug("Setting up Swarm service components")
@ -344,7 +345,7 @@ Start is called when the stack is started
*/
// implements the node.Service interface
func (self *Swarm) Start(srv *p2p.Server) error {
self.startTime = time.Now()
startTime := time.Now()
self.tracerClose = tracing.Closer
@ -396,28 +397,30 @@ func (self *Swarm) Start(srv *p2p.Server) error {
}()
}
self.periodicallyUpdateGauges()
doneC := make(chan struct{})
self.cleanupFuncs = append(self.cleanupFuncs, func() error {
close(doneC)
return nil
})
go func(time.Time) {
for {
select {
case <-time.After(updateGaugesPeriod):
uptimeGauge.Update(time.Since(startTime).Nanoseconds())
requestsCacheGauge.Update(int64(self.netStore.RequestsCacheLen()))
case <-doneC:
return
}
}
}(startTime)
startCounter.Inc(1)
self.streamer.Start(srv)
return nil
}
func (self *Swarm) periodicallyUpdateGauges() {
ticker := time.NewTicker(updateGaugesPeriod)
go func() {
for range ticker.C {
self.updateGauges()
}
}()
}
func (self *Swarm) updateGauges() {
uptimeGauge.Update(time.Since(self.startTime).Nanoseconds())
requestsCacheGauge.Update(int64(self.netStore.RequestsCacheLen()))
}
// implements the node.Service interface
// stops all component services.
func (self *Swarm) Stop() error {
@ -452,6 +455,14 @@ func (self *Swarm) Stop() error {
if self.stateStore != nil {
self.stateStore.Close()
}
for _, cleanF := range self.cleanupFuncs {
err = cleanF()
if err != nil {
log.Error("encountered an error while running cleanup function", "err", err)
break
}
}
return err
}