Skip to content

Commit

Permalink
Fixes timer resources leak in CountdownToGenesis (#7175)
Browse files Browse the repository at this point in the history
* fixes timer leak in CountdownToGenesis
* Merge branch 'master' into fix-unclosed-timer-in-countdown
* Merge refs/heads/master into fix-unclosed-timer-in-countdown
  • Loading branch information
farazdagi authored Sep 4, 2020
1 parent e6277ec commit b6607fa
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 21 deletions.
2 changes: 2 additions & 0 deletions shared/slotutil/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ go_test(
"countdown_test.go",
"slotticker_test.go",
"slottime_test.go",
"slotutil_test.go",
],
embed = [":go_default_library"],
deps = [
"//shared/params:go_default_library",
"//shared/roughtime:go_default_library",
"//shared/testutil/require:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
],
)
29 changes: 17 additions & 12 deletions shared/slotutil/countdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,38 @@ var log = logrus.WithField("prefix", "slotutil")
// of genesis validators.
func CountdownToGenesis(ctx context.Context, genesisTime time.Time, genesisValidatorCount uint64) {
ticker := time.NewTicker(params.BeaconConfig().GenesisCountdownInterval)
timeTillGenesis := genesisTime.Sub(roughtime.Now())
defer func() {
// Used in anonymous function to make sure that updated (per second) ticker is stopped.
ticker.Stop()
}()
logFields := logrus.Fields{
"genesisValidators": fmt.Sprintf("%d", genesisValidatorCount),
"genesisTime": fmt.Sprintf("%v", genesisTime),
}
secondTimerActivated := false
for {
select {
case <-time.After(timeTillGenesis):
currentTime := roughtime.Now()
if currentTime.After(genesisTime) {
log.WithFields(logFields).Info("Chain genesis time reached")
return
}
timeRemaining := genesisTime.Sub(currentTime)
if !secondTimerActivated && timeRemaining <= 2*time.Minute {
ticker.Stop()
// Replace ticker with a one having higher granularity.
ticker = time.NewTicker(time.Second)
secondTimerActivated = true
}
select {
case <-ticker.C:
currentTime := roughtime.Now()
if currentTime.After(genesisTime) {
log.WithFields(logFields).Info("Chain genesis time reached")
return
}
timeRemaining := genesisTime.Sub(currentTime)
if timeRemaining <= 2*time.Minute {
ticker = time.NewTicker(time.Second)
}
if timeRemaining >= time.Second {
log.WithFields(logFields).Infof(
"%s until chain genesis",
timeRemaining.Truncate(time.Second),
)
}
case <-ctx.Done():
log.Debug("Context closed, exiting routine")
return
}
}
Expand Down
39 changes: 30 additions & 9 deletions shared/slotutil/countdown_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,34 @@ func TestCountdownToGenesis(t *testing.T) {
config.GenesisCountdownInterval = time.Millisecond * 500
params.OverrideBeaconConfig(config)

firstStringResult := "1s until chain genesis"
genesisReached := "Chain genesis time reached"
CountdownToGenesis(
context.Background(),
roughtime.Now().Add(2*time.Second),
params.BeaconConfig().MinGenesisActiveValidatorCount,
)
require.LogsContain(t, hook, firstStringResult)
require.LogsContain(t, hook, genesisReached)
t.Run("normal countdown", func(t *testing.T) {
defer hook.Reset()
firstStringResult := "1s until chain genesis"
genesisReached := "Chain genesis time reached"
CountdownToGenesis(
context.Background(),
roughtime.Now().Add(2*time.Second),
params.BeaconConfig().MinGenesisActiveValidatorCount,
)
require.LogsContain(t, hook, firstStringResult)
require.LogsContain(t, hook, genesisReached)
})

t.Run("close context", func(t *testing.T) {
defer hook.Reset()
ctx, cancel := context.WithCancel(context.Background())
go func() {
time.AfterFunc(1500*time.Millisecond, func() {
cancel()
})
}()
CountdownToGenesis(
ctx,
roughtime.Now().Add(5*time.Second),
params.BeaconConfig().MinGenesisActiveValidatorCount,
)
require.LogsContain(t, hook, "4s until chain genesis")
require.LogsContain(t, hook, "Context closed, exiting routine")
require.LogsDoNotContain(t, hook, "Chain genesis time reached")
})
}
16 changes: 16 additions & 0 deletions shared/slotutil/slotutil_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package slotutil

import (
"io/ioutil"
"os"
"testing"

"github.com/sirupsen/logrus"
)

func TestMain(m *testing.M) {
logrus.SetLevel(logrus.DebugLevel)
logrus.SetOutput(ioutil.Discard)

os.Exit(m.Run())
}

0 comments on commit b6607fa

Please sign in to comment.