agent/util/wrapgo/wrapped.go (45 lines of code) (raw):

package wrapgo import ( "runtime/debug" "sync" "fmt" "os" ) // PanicHandler is used in wrapped goroutine initiation type PanicHandler func(interface{}, []byte) var ( _defaultPanicHandler PanicHandler = defaultPanicHandler _defaultPanicHandlerInitLock sync.Mutex ) func defaultPanicHandler(payload interface{}, stack []byte) { panic(payload) } // SetDefaultPanicHandler sets default panic handler for GoWithDefaultPanicHandler. // It should be called at initialization only once. func SetDefaultPanicHandler(handler PanicHandler) PanicHandler { _defaultPanicHandlerInitLock.Lock() defer _defaultPanicHandlerInitLock.Unlock() oldPanicHandler := _defaultPanicHandler _defaultPanicHandler = handler return oldPanicHandler } // CallDefaultPanicHandler calls set defaultPanicHandler function as wrapper func CallDefaultPanicHandler(payload interface{}, stack []byte) { _defaultPanicHandler(payload, stack) } // GoWithPanicHandler initiate goroutine with panic handler func GoWithPanicHandler(f func(), handler PanicHandler) { go CallWithPanicHandler(f, handler) } // CallWithPanicHandler call f with panic handler func CallWithPanicHandler(f func(), handler PanicHandler) { defer func () { if panicPayload := recover(); panicPayload != nil { stacktrace := debug.Stack() fmt.Fprintf(os.Stderr, "panic: %v", panicPayload) fmt.Fprint(os.Stderr, string(stacktrace)) handler(panicPayload, stacktrace) } }() f() } // GoWithDefaultPanicHandler initiate goroutine with default panic handler func GoWithDefaultPanicHandler(f func()) { GoWithPanicHandler(f, _defaultPanicHandler) } // CallWithPanicHandler call f with panic handler func CallWithDefaultPanicHandler(f func()) { CallWithPanicHandler(f, _defaultPanicHandler) }