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  }