diff --git a/connmgr/connmanager.go b/connmgr/connmanager.go index d2790ec42..d5b0f5bfa 100644 --- a/connmgr/connmanager.go +++ b/connmgr/connmanager.go @@ -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) } diff --git a/connmgr/log.go b/connmgr/log.go index d34006d75..c7a747829 100644 --- a/connmgr/log.go +++ b/connmgr/log.go @@ -11,3 +11,4 @@ import ( var log, _ = logger.Get(logger.SubsystemTags.CMGR) var spawn = panics.GoroutineWrapperFuncWithPanicHandler(log) +var spawnAfter = panics.AfterFuncWrapperFuncWithPanicHandler(log) diff --git a/peer/log.go b/peer/log.go index 0feb4f535..0b086dedb 100644 --- a/peer/log.go +++ b/peer/log.go @@ -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 { diff --git a/peer/peer.go b/peer/peer.go index a647c3579..26d59934a 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -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() }) diff --git a/util/panics/panics.go b/util/panics/panics.go index 4cbd5a50a..a3550eb8d 100644 --- a/util/panics/panics.go +++ b/util/panics/panics.go @@ -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() + }) + } +}