github.com/kaydxh/golang@v0.0.131/go/runtime/panic.go (about) 1 /* 2 *Copyright (c) 2022, kaydxh 3 * 4 *Permission is hereby granted, free of charge, to any person obtaining a copy 5 *of this software and associated documentation files (the "Software"), to deal 6 *in the Software without restriction, including without limitation the rights 7 *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 *copies of the Software, and to permit persons to whom the Software is 9 *furnished to do so, subject to the following conditions: 10 * 11 *The above copyright notice and this permission notice shall be included in all 12 *copies or substantial portions of the Software. 13 * 14 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 *SOFTWARE. 21 */ 22 package runtime 23 24 import ( 25 "fmt" 26 "net/http" 27 28 "github.com/sirupsen/logrus" 29 ) 30 31 // PanicHandlers is a list of functions which will be invoked when a panic happens. 32 var PanicHandlers = []func(interface{}){logPanic} 33 34 //must use defer Recover() 35 //not effective for calling defer func() {Recover()}() 36 func Recover() { 37 if r := recover(); r != nil { 38 for _, fn := range PanicHandlers { 39 fn(r) 40 } 41 } 42 } 43 44 // logPanic logs the caller tree when a panic occurs (except in the special case of http.ErrAbortHandler). 45 func logPanic(r interface{}) { 46 if r == http.ErrAbortHandler { 47 // honor the http.ErrAbortHandler sentinel panic value: 48 // ErrAbortHandler is a sentinel panic value to abort a handler. 49 // While any panic from ServeHTTP aborts the response to the client, 50 // panicking with ErrAbortHandler also suppresses logging of a stack trace to the server's error log. 51 return 52 } 53 54 // Same as stdlib http server code. Manually allocate stack trace buffer size 55 // to prevent excessively large logs 56 stacktrace := GetCallStackTrace() 57 if _, ok := r.(string); ok { 58 logrus.Errorf("Observed a panic: %s\n%s", r, stacktrace) 59 } else { 60 logrus.Errorf("Observed a panic: %#v (%v)\n%s", r, r, stacktrace) 61 } 62 } 63 64 // RecoverFromPanic replaces the specified error with an error containing the 65 // original error, and the call tree when a panic occurs. This enables error 66 // handlers to handle errors and panics the same way. 67 func RecoverFromPanic(err *error) { 68 if r := recover(); r != nil { 69 // Same as stdlib http server code. Manually allocate stack trace buffer size 70 // to prevent excessively large logs 71 stacktrace := GetCallStackTrace() 72 *err = fmt.Errorf( 73 "recovered from panic %q. (err=%v) Call stack:\n%s", 74 r, 75 *err, 76 stacktrace) 77 } 78 } 79 80 // Must panics on non-nil errors. Useful to handling programmer level errors 81 func Must(err error) { 82 if err != nil { 83 panic(err) 84 } 85 }