recovery.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. package warden
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "runtime"
  7. "go-common/library/ecode"
  8. "go-common/library/log"
  9. "google.golang.org/grpc"
  10. "google.golang.org/grpc/codes"
  11. "google.golang.org/grpc/status"
  12. )
  13. // recovery is a server interceptor that recovers from any panics.
  14. func (s *Server) recovery() grpc.UnaryServerInterceptor {
  15. return func(ctx context.Context, req interface{}, args *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
  16. defer func() {
  17. if rerr := recover(); rerr != nil {
  18. const size = 64 << 10
  19. buf := make([]byte, size)
  20. rs := runtime.Stack(buf, false)
  21. if rs > size {
  22. rs = size
  23. }
  24. buf = buf[:rs]
  25. pl := fmt.Sprintf("grpc server panic: %v\n%v\n%s\n", req, rerr, buf)
  26. fmt.Fprintf(os.Stderr, pl)
  27. log.Error(pl)
  28. err = status.Errorf(codes.Unknown, ecode.ServerErr.Error())
  29. }
  30. }()
  31. resp, err = handler(ctx, req)
  32. return
  33. }
  34. }
  35. // recovery return a client interceptor that recovers from any panics.
  36. func (c *Client) recovery() grpc.UnaryClientInterceptor {
  37. return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) (err error) {
  38. defer func() {
  39. if rerr := recover(); rerr != nil {
  40. const size = 64 << 10
  41. buf := make([]byte, size)
  42. rs := runtime.Stack(buf, false)
  43. if rs > size {
  44. rs = size
  45. }
  46. buf = buf[:rs]
  47. pl := fmt.Sprintf("grpc client panic: %v\n%v\n%v\n%s\n", req, reply, rerr, buf)
  48. fmt.Fprintf(os.Stderr, pl)
  49. log.Error(pl)
  50. err = ecode.ServerErr
  51. }
  52. }()
  53. err = invoker(ctx, method, req, reply, cc, opts...)
  54. return
  55. }
  56. }