github.com/Rookout/GoSDK@v0.1.48/pkg/utils/gosafe.go (about) 1 package utils 2 3 import ( 4 "context" 5 "runtime/debug" 6 _ "unsafe" 7 8 "github.com/Rookout/GoSDK/pkg/rookoutErrors" 9 ) 10 11 type OnPanicFuncType func(error) 12 13 var OnPanicFunc OnPanicFuncType 14 15 type panicInfo struct { 16 didPanic bool 17 } 18 19 const allowPanic = false 20 21 func SetOnPanicFunc(onPanic OnPanicFuncType) { 22 OnPanicFunc = onPanic 23 } 24 25 func createHandlePanicFunc(info *panicInfo) func() { 26 return func() { 27 if allowPanic { 28 return 29 } 30 31 if v := recover(); v != nil { 32 if OnPanicFunc != nil { 33 OnPanicFunc(rookoutErrors.NewUnknownError(v)) 34 } 35 36 if info != nil { 37 info.didPanic = true 38 } 39 40 return 41 } 42 43 if info != nil { 44 info.didPanic = false 45 } 46 } 47 } 48 49 func CreateGoroutine(f func()) { 50 handlePanic := createHandlePanicFunc(nil) 51 52 53 go func() { 54 defer handlePanic() 55 debug.SetPanicOnFault(true) 56 57 f() 58 }() 59 } 60 61 62 63 func CreateRetryingGoroutine(ctx context.Context, f func()) { 64 CreateGoroutine(func() { 65 for { 66 info := &panicInfo{} 67 handlePanic := createHandlePanicFunc(info) 68 69 func() { 70 defer handlePanic() 71 f() 72 }() 73 74 select { 75 case <-ctx.Done(): 76 return 77 default: 78 if !info.didPanic { 79 return 80 } 81 } 82 } 83 }) 84 } 85 86 87 func CreateBlockingGoroutine(f func()) { 88 waitChan := make(chan interface{}) 89 90 CreateGoroutine(func() { 91 defer func() { 92 waitChan <- nil 93 }() 94 95 f() 96 }) 97 98 <-waitChan 99 }