[NOD-696] Handle panics on time.AfterFunc (#600)

* [NOD-696] Handle panics on time.AfterFunc

* [NOD-696] Fix comment

* [NOD-696] Rename afterFunc->spawnAfter
This commit is contained in:
Ori Newman 2020-01-27 11:12:23 +02:00 committed by Svarog
parent fd2bbf3557
commit a10320ad7b
5 changed files with 32 additions and 8 deletions

View File

@ -232,9 +232,9 @@ func (cm *ConnManager) handleFailedConn(c *ConnReq, err error) {
if shouldWriteLog {
log.Debugf("Retrying further connections to %s every %s", c, d)
}
time.AfterFunc(d, func() {
spawnAfter(d, func() {
cm.Connect(c)
})
}, nil)
} else if cm.cfg.GetNewAddress != nil {
cm.failedAttempts++
if cm.failedAttempts >= maxFailedAttempts {
@ -243,9 +243,7 @@ func (cm *ConnManager) handleFailedConn(c *ConnReq, err error) {
"-- retrying further connections every %s", maxFailedAttempts,
cm.cfg.RetryDuration)
}
time.AfterFunc(cm.cfg.RetryDuration, func() {
cm.NewConnReq()
})
spawnAfter(cm.cfg.RetryDuration, cm.NewConnReq, cm.handlePanic)
} else {
spawn(cm.NewConnReq, cm.handlePanic)
}

View File

@ -11,3 +11,4 @@ import (
var log, _ = logger.Get(logger.SubsystemTags.CMGR)
var spawn = panics.GoroutineWrapperFuncWithPanicHandler(log)
var spawnAfter = panics.AfterFuncWrapperFuncWithPanicHandler(log)

View File

@ -23,6 +23,7 @@ const (
var log, _ = logger.Get(logger.SubsystemTags.PEER)
var spawn = panics.GoroutineWrapperFunc(log)
var spawnAfter = panics.AfterFuncWrapperFunc(log)
// formatLockTime returns a transaction lock time as a human-readable string.
func formatLockTime(lockTime uint64) string {

View File

@ -1346,7 +1346,7 @@ cleanup:
func (p *Peer) inHandler() {
// The timer is stopped when a new message is received and reset after it
// is processed.
idleTimer := time.AfterFunc(idleTimeout, func() {
idleTimer := spawnAfter(idleTimeout, func() {
log.Warnf("Peer %s no answer for %s -- disconnecting", p, idleTimeout)
p.Disconnect()
})

View File

@ -4,6 +4,7 @@ import (
"github.com/kaspanet/kaspad/logs"
"github.com/kaspanet/kaspad/signal"
"runtime/debug"
"time"
)
// HandlePanic recovers panics, log them, runs an optional panicHandler,
@ -22,7 +23,7 @@ func HandlePanic(log logs.Logger, goroutineStackTrace []byte, panicHandler func(
}
}
// GoroutineWrapperFunc returns a goroutine wrapper function that handles panics and write them to the log.
// GoroutineWrapperFunc returns a goroutine wrapper function that handles panics and writes them to the log.
func GoroutineWrapperFunc(log logs.Logger) func(func()) {
return func(f func()) {
stackTrace := debug.Stack()
@ -34,7 +35,7 @@ func GoroutineWrapperFunc(log logs.Logger) func(func()) {
}
// GoroutineWrapperFuncWithPanicHandler returns a goroutine wrapper function that handles panics,
// write them to the log, and executes a handler function for panics.
// writes them to the log, and executes a handler function for panics.
func GoroutineWrapperFuncWithPanicHandler(log logs.Logger) func(func(), func()) {
return func(f func(), panicHandler func()) {
stackTrace := debug.Stack()
@ -44,3 +45,26 @@ func GoroutineWrapperFuncWithPanicHandler(log logs.Logger) func(func(), func())
}()
}
}
// AfterFuncWrapperFunc returns a time.AfterFunc wrapper function that handles panics.
func AfterFuncWrapperFunc(log logs.Logger) func(d time.Duration, f func()) *time.Timer {
return func(d time.Duration, f func()) *time.Timer {
stackTrace := debug.Stack()
return time.AfterFunc(d, func() {
defer HandlePanic(log, stackTrace, nil)
f()
})
}
}
// AfterFuncWrapperFuncWithPanicHandler returns a time.AfterFunc wrapper function that handles panics,
// writes them to the log, and executes a handler function for panics.
func AfterFuncWrapperFuncWithPanicHandler(log logs.Logger) func(d time.Duration, f func(), panicHandler func()) *time.Timer {
return func(d time.Duration, f func(), panicHandler func()) *time.Timer {
stackTrace := debug.Stack()
return time.AfterFunc(d, func() {
defer HandlePanic(log, stackTrace, panicHandler)
f()
})
}
}