mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-09-14 05:20:11 +00:00

* [NOD-696] Handle panics on time.AfterFunc * [NOD-696] Fix comment * [NOD-696] Rename afterFunc->spawnAfter
71 lines
2.2 KiB
Go
71 lines
2.2 KiB
Go
package panics
|
|
|
|
import (
|
|
"github.com/kaspanet/kaspad/logs"
|
|
"github.com/kaspanet/kaspad/signal"
|
|
"runtime/debug"
|
|
"time"
|
|
)
|
|
|
|
// HandlePanic recovers panics, log them, runs an optional panicHandler,
|
|
// and then initiates a clean shutdown.
|
|
func HandlePanic(log logs.Logger, goroutineStackTrace []byte, panicHandler func()) {
|
|
if err := recover(); err != nil {
|
|
log.Criticalf("Fatal error: %+v", err)
|
|
if goroutineStackTrace != nil {
|
|
log.Criticalf("goroutine stack trace: %s", goroutineStackTrace)
|
|
}
|
|
log.Criticalf("Stack trace: %s", debug.Stack())
|
|
if panicHandler != nil {
|
|
panicHandler()
|
|
}
|
|
signal.PanicShutdownChannel <- struct{}{}
|
|
}
|
|
}
|
|
|
|
// 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()
|
|
go func() {
|
|
defer HandlePanic(log, stackTrace, nil)
|
|
f()
|
|
}()
|
|
}
|
|
}
|
|
|
|
// GoroutineWrapperFuncWithPanicHandler returns a goroutine wrapper function that handles 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()
|
|
go func() {
|
|
defer HandlePanic(log, stackTrace, panicHandler)
|
|
f()
|
|
}()
|
|
}
|
|
}
|
|
|
|
// 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()
|
|
})
|
|
}
|
|
}
|