github.com/weedge/lib@v0.0.0-20230424045628-a36dcc1d90e4/runtimer/goroutine.go (about)

     1  package runtimer
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"runtime/debug"
     8  	"sync"
     9  	"time"
    10  )
    11  
    12  // GoSafely WaitGroup wraps a `go func()` with recover()
    13  func GoSafely(wg *sync.WaitGroup, ignoreRecover bool, handler func(), catchFunc func(r interface{}), w io.Writer) {
    14  	if w == nil {
    15  		w = os.Stderr
    16  	}
    17  	if wg != nil {
    18  		wg.Add(1)
    19  	}
    20  	go func() {
    21  		defer func() {
    22  			if r := recover(); r != nil {
    23  				if !ignoreRecover {
    24  					fmt.Fprintf(w, "%s goroutine panic: %v\n%s\n", time.Now(), r, string(debug.Stack()))
    25  				}
    26  				if catchFunc != nil {
    27  					if wg != nil {
    28  						wg.Add(1)
    29  					}
    30  					go func() {
    31  						defer func() {
    32  							if p := recover(); p != nil {
    33  								if !ignoreRecover {
    34  									fmt.Fprintf(w, "recover goroutine panic:%v\n%s\n", p, string(debug.Stack()))
    35  								}
    36  							}
    37  
    38  							if wg != nil {
    39  								wg.Done()
    40  							}
    41  						}()
    42  						catchFunc(r)
    43  					}()
    44  				}
    45  			}
    46  			if wg != nil {
    47  				wg.Done()
    48  			}
    49  		}()
    50  		handler()
    51  	}()
    52  	return
    53  }
    54  
    55  // GoUnterminated is used for which goroutine wanna long live as its process.
    56  // @period: sleep time duration after panic to defeat @handle panic so frequently. if it is not positive,
    57  //          the @handle will be invoked asap after panic.
    58  func GoUnterminated(handle func(), wg *sync.WaitGroup, ignoreRecover bool, period time.Duration, w io.Writer) {
    59  	GoSafely(wg,
    60  		ignoreRecover,
    61  		handle,
    62  		func(r interface{}) {
    63  			if period > 0 {
    64  				time.Sleep(period)
    65  			}
    66  			GoUnterminated(handle, wg, ignoreRecover, period, w)
    67  		}, w,
    68  	)
    69  	return
    70  }