@@ -6,12 +6,16 @@ package plugin
66import (
77 "bytes"
88 "context"
9+ "runtime/debug"
910 "unicode/utf8"
1011
1112 plugin "github.com/hashicorp/go-plugin"
13+ "github.com/rs/zerolog/log"
1214 "google.golang.org/grpc"
15+ "google.golang.org/grpc/codes"
1316 "google.golang.org/grpc/encoding"
1417 _ "google.golang.org/grpc/encoding/proto"
18+ "google.golang.org/grpc/status"
1519)
1620
1721func init () {
@@ -83,6 +87,18 @@ func (m *GRPCClient) StoreData(req *StoreReq) (*StoreRes, error) {
8387 return m .client .StoreData (context .Background (), req )
8488}
8589
90+ // recoverPanic converts a panic into a gRPC Internal error. The full stack
91+ // trace is logged locally; only a short message is sent over the wire.
92+ // The message is prefixed with "panic in provider " so the caller can
93+ // distinguish recovered panics from other Internal errors.
94+ func recoverPanic (method string , retErr * error ) {
95+ if r := recover (); r != nil {
96+ stack := debug .Stack ()
97+ log .Error ().Str ("method" , method ).Interface ("panic" , r ).Str ("stack" , string (stack )).Msg ("recovered panic in provider" )
98+ * retErr = status .Errorf (codes .Internal , "panic in provider %s: %v" , method , r )
99+ }
100+ }
101+
86102// Here is the gRPC server that GRPCClient talks to.
87103type GRPCServer struct {
88104 // This is the real implementation
@@ -95,11 +111,13 @@ func (m *GRPCServer) Heartbeat(ctx context.Context, req *HeartbeatReq) (*Heartbe
95111 return m .Impl .Heartbeat (req )
96112}
97113
98- func (m * GRPCServer ) ParseCLI (ctx context.Context , req * ParseCLIReq ) (* ParseCLIRes , error ) {
114+ func (m * GRPCServer ) ParseCLI (ctx context.Context , req * ParseCLIReq ) (resp * ParseCLIRes , err error ) {
115+ defer recoverPanic ("ParseCLI" , & err )
99116 return m .Impl .ParseCLI (req )
100117}
101118
102- func (m * GRPCServer ) Connect (ctx context.Context , req * ConnectReq ) (* ConnectRes , error ) {
119+ func (m * GRPCServer ) Connect (ctx context.Context , req * ConnectReq ) (resp * ConnectRes , err error ) {
120+ defer recoverPanic ("Connect" , & err )
103121 conn , err := m .broker .Dial (req .CallbackServer )
104122 if err != nil {
105123 return nil , err
@@ -112,11 +130,13 @@ func (m *GRPCServer) Connect(ctx context.Context, req *ConnectReq) (*ConnectRes,
112130 return m .Impl .Connect (req , a )
113131}
114132
115- func (m * GRPCServer ) Disconnect (ctx context.Context , req * DisconnectReq ) (* DisconnectRes , error ) {
133+ func (m * GRPCServer ) Disconnect (ctx context.Context , req * DisconnectReq ) (resp * DisconnectRes , err error ) {
134+ defer recoverPanic ("Disconnect" , & err )
116135 return m .Impl .Disconnect (req )
117136}
118137
119- func (m * GRPCServer ) MockConnect (ctx context.Context , req * ConnectReq ) (* ConnectRes , error ) {
138+ func (m * GRPCServer ) MockConnect (ctx context.Context , req * ConnectReq ) (resp * ConnectRes , err error ) {
139+ defer recoverPanic ("MockConnect" , & err )
120140 conn , err := m .broker .Dial (req .CallbackServer )
121141 if err != nil {
122142 return nil , err
@@ -129,20 +149,23 @@ func (m *GRPCServer) MockConnect(ctx context.Context, req *ConnectReq) (*Connect
129149 return m .Impl .MockConnect (req , a )
130150}
131151
132- func (m * GRPCServer ) Shutdown (ctx context.Context , req * ShutdownReq ) (* ShutdownRes , error ) {
152+ func (m * GRPCServer ) Shutdown (ctx context.Context , req * ShutdownReq ) (resp * ShutdownRes , err error ) {
153+ defer recoverPanic ("Shutdown" , & err )
133154 return m .Impl .Shutdown (req )
134155}
135156
136- func (m * GRPCServer ) GetData (ctx context.Context , req * DataReq ) (* DataRes , error ) {
137- resp , err := m .Impl .GetData (req )
157+ func (m * GRPCServer ) GetData (ctx context.Context , req * DataReq ) (resp * DataRes , err error ) {
158+ defer recoverPanic ("GetData" , & err )
159+ resp , err = m .Impl .GetData (req )
138160 if err != nil {
139161 return nil , err
140162 }
141163 sanitizeDataRes (resp )
142164 return resp , nil
143165}
144166
145- func (m * GRPCServer ) StoreData (ctx context.Context , req * StoreReq ) (* StoreRes , error ) {
167+ func (m * GRPCServer ) StoreData (ctx context.Context , req * StoreReq ) (resp * StoreRes , err error ) {
168+ defer recoverPanic ("StoreData" , & err )
146169 return m .Impl .StoreData (req )
147170}
148171
0 commit comments