@@ -182,6 +182,27 @@ func (r *gRPCReporter) closeGRPCConn() {
182182 }
183183}
184184
185+ // sendWithRecover invokes send and recovers from a panic raised while encoding or
186+ // transmitting a single message, so that one corrupted payload cannot tear down the
187+ // whole send pipeline. On a recovered panic it logs via the existing logger and
188+ // returns recovered=true, telling the caller to skip the current message and keep
189+ // streaming the rest.
190+ //
191+ // Such a panic originates in protobuf size/marshal computation (the #13885 crash),
192+ // which runs before any bytes are written to the stream, so the stream stays valid
193+ // and may be reused for the next message. Should a panic ever leave the stream
194+ // inconsistent, the following send returns an error and the caller reconnects.
195+ func (r * gRPCReporter ) sendWithRecover (send func () error ) (recovered bool , err error ) {
196+ defer func () {
197+ if rec := recover (); rec != nil {
198+ r .logger .Errorf ("gRPCReporter recovered from panic while sending, skip current message: %v" , rec )
199+ recovered = true
200+ }
201+ }()
202+ err = send ()
203+ return recovered , err
204+ }
205+
185206// nolint
186207func (r * gRPCReporter ) initSendPipeline () {
187208 if r .traceClient == nil {
@@ -210,9 +231,12 @@ func (r *gRPCReporter) initSendPipeline() {
210231 continue StreamLoop
211232 }
212233 for s := range r .tracingSendCh {
213- err = stream .Send (s )
214- if err != nil {
215- r .logger .Errorf ("send segment error %v" , err )
234+ recovered , sendErr := r .sendWithRecover (func () error { return stream .Send (s ) })
235+ if recovered {
236+ continue
237+ }
238+ if sendErr != nil {
239+ r .logger .Errorf ("send segment error %v" , sendErr )
216240 r .closeTracingStream (stream )
217241 continue StreamLoop
218242 }
@@ -245,11 +269,14 @@ func (r *gRPCReporter) initSendPipeline() {
245269 continue StreamLoop
246270 }
247271 for s := range r .metricsSendCh {
248- err = stream . Send ( & agentv3. MeterDataCollection {
249- MeterData : s ,
272+ recovered , sendErr := r . sendWithRecover ( func () error {
273+ return stream . Send ( & agentv3. MeterDataCollection { MeterData : s })
250274 })
251- if err != nil {
252- r .logger .Errorf ("send metrics error %v" , err )
275+ if recovered {
276+ continue
277+ }
278+ if sendErr != nil {
279+ r .logger .Errorf ("send metrics error %v" , sendErr )
253280 r .closeMetricsStream (stream )
254281 continue StreamLoop
255282 }
@@ -281,9 +308,12 @@ func (r *gRPCReporter) initSendPipeline() {
281308 continue StreamLoop
282309 }
283310 for s := range r .logSendCh {
284- err = stream .Send (s )
285- if err != nil {
286- r .logger .Errorf ("send log error %v" , err )
311+ recovered , sendErr := r .sendWithRecover (func () error { return stream .Send (s ) })
312+ if recovered {
313+ continue
314+ }
315+ if sendErr != nil {
316+ r .logger .Errorf ("send log error %v" , sendErr )
287317 r .closeLogStream (stream )
288318 continue StreamLoop
289319 }
@@ -325,9 +355,12 @@ func (r *gRPCReporter) initSendPipeline() {
325355 }
326356 r .logger .Infof ("Sending profile task: TaskID='%s', PayloadSize=%d, IsLast=%v" ,
327357 task .TaskID , len (task .Payload ), task .IsLast )
328- err = stream .Send (profileData )
329- if err != nil {
330- r .logger .Errorf ("send profile data error %v" , err )
358+ recovered , sendErr := r .sendWithRecover (func () error { return stream .Send (profileData ) })
359+ if recovered {
360+ continue
361+ }
362+ if sendErr != nil {
363+ r .logger .Errorf ("send profile data error %v" , sendErr )
331364 r .closeProfileStream (stream )
332365 continue StreamLoop
333366 }
0 commit comments