1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 |
- package waitutil
- import (
- "fmt"
- "log"
- "runtime"
- )
- // logPanic logs the caller tree when a panic occurs.
- func logPanic(r interface{}) {
- callers := getCallers(r)
- if _, ok := r.(string); ok {
- log.Printf("observed a panic: %s\n%v", r, callers)
- } else {
- log.Printf("observed a panic: %#v (%v)\n%v", r, r, callers)
- }
- }
- func getCallers(r interface{}) string {
- callers := ""
- for i := 0; true; i++ {
- _, file, line, ok := runtime.Caller(i)
- if !ok {
- break
- }
- callers = callers + fmt.Sprintf("%v:%v\n", file, line)
- }
- return callers
- }
- // PanicHandlers is a list of functions which will be invoked when a panic happens.
- var PanicHandlers = []func(interface{}){logPanic}
- // HandleCrash simply catches a crash and logs an error. Meant to be called via
- // defer. Additional context-specific handlers can be provided, and will be
- // called in case of panic. HandleCrash actually crashes, after calling the
- // handlers and logging the panic message.
- func HandleCrash(additionalHandlers ...func(interface{})) {
- if r := recover(); r != nil {
- for _, fn := range PanicHandlers {
- fn(r)
- }
- for _, fn := range additionalHandlers {
- fn(r)
- }
- // Actually proceed to panic.
- panic(r)
- }
- }
|