github.com/prysmaticlabs/prysm@v1.4.4/shared/messagehandler/messagehandler.go (about) 1 // Package messagehandler contains useful helpers for recovering 2 // from panic conditions at runtime and logging their trace. 3 package messagehandler 4 5 import ( 6 "context" 7 "fmt" 8 "runtime/debug" 9 10 pubsub "github.com/libp2p/go-libp2p-pubsub" 11 "github.com/sirupsen/logrus" 12 "go.opencensus.io/trace" 13 ) 14 15 const noMsgData = "message contains no data" 16 17 var log = logrus.WithField("prefix", "message-handler") 18 19 // SafelyHandleMessage will recover and log any panic that occurs from the 20 // function argument. 21 func SafelyHandleMessage(ctx context.Context, fn func(ctx context.Context, message *pubsub.Message) error, msg *pubsub.Message) { 22 defer HandlePanic(ctx, msg) 23 24 // Fingers crossed that it doesn't panic... 25 if err := fn(ctx, msg); err != nil { 26 // Report any error on the span, if one exists. 27 if span := trace.FromContext(ctx); span != nil { 28 span.SetStatus(trace.Status{ 29 Code: trace.StatusCodeInternal, 30 Message: err.Error(), 31 }) 32 } 33 } 34 } 35 36 // HandlePanic returns a panic handler function that is used to 37 // capture a panic. 38 func HandlePanic(ctx context.Context, msg *pubsub.Message) { 39 if r := recover(); r != nil { 40 printedMsg := noMsgData 41 if msg != nil { 42 printedMsg = msg.String() 43 } 44 log.WithFields(logrus.Fields{ 45 "r": r, 46 "msg": printedMsg, 47 }).Error("Panicked when handling p2p message! Recovering...") 48 49 debug.PrintStack() 50 51 if ctx == nil { 52 return 53 } 54 if span := trace.FromContext(ctx); span != nil { 55 span.SetStatus(trace.Status{ 56 Code: trace.StatusCodeInternal, 57 Message: fmt.Sprintf("Panic: %v", r), 58 }) 59 } 60 } 61 }