github.com/dubbogo/gost@v1.14.0/runtime/goroutine.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package gxruntime 19 20 import ( 21 "fmt" 22 "os" 23 "runtime/debug" 24 "sync" 25 "time" 26 ) 27 28 // GoSafely wraps a `go func()` with recover() 29 func GoSafely(wg *sync.WaitGroup, ignoreRecover bool, handler func(), catchFunc func(r interface{})) { 30 if wg != nil { 31 wg.Add(1) 32 } 33 go func() { 34 defer func() { 35 if r := recover(); r != nil { 36 if !ignoreRecover { 37 fmt.Fprintf(os.Stderr, "%s goroutine panic: %v\n%s\n", 38 time.Now(), r, string(debug.Stack())) 39 } 40 if catchFunc != nil { 41 if wg != nil { 42 wg.Add(1) 43 } 44 go func() { 45 defer func() { 46 if p := recover(); p != nil { 47 if !ignoreRecover { 48 fmt.Fprintf(os.Stderr, "recover goroutine panic:%v\n%s\n", 49 p, string(debug.Stack())) 50 } 51 } 52 53 if wg != nil { 54 wg.Done() 55 } 56 }() 57 catchFunc(r) 58 }() 59 } 60 } 61 if wg != nil { 62 wg.Done() 63 } 64 }() 65 handler() 66 }() 67 } 68 69 // GoUnterminated is used for which goroutine wanna long live as its process. 70 // @period: sleep time duration after panic to defeat @handle panic so frequently. if it is not positive, 71 // the @handle will be invoked asap after panic. 72 func GoUnterminated(handle func(), wg *sync.WaitGroup, ignoreRecover bool, period time.Duration) { 73 GoSafely(wg, 74 ignoreRecover, 75 handle, 76 func(r interface{}) { 77 if period > 0 { 78 time.Sleep(period) 79 } 80 GoUnterminated(handle, wg, ignoreRecover, period) 81 }, 82 ) 83 }