From 0a9bc09884ad3e0c481cf4d4c78d477620e552a6 Mon Sep 17 00:00:00 2001 From: Mark van Renswoude Date: Tue, 14 Feb 2017 22:45:59 +0100 Subject: [PATCH] Fixed #11: Improve stack traces for exceptions Fixed #12: Stack overflow when an exception occurs in the middleware --- Tapeti/Connection/TapetiConsumer.cs | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/Tapeti/Connection/TapetiConsumer.cs b/Tapeti/Connection/TapetiConsumer.cs index b3b3ed6..e3ede98 100644 --- a/Tapeti/Connection/TapetiConsumer.cs +++ b/Tapeti/Connection/TapetiConsumer.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.ExceptionServices; using RabbitMQ.Client; using Tapeti.Config; using Tapeti.Helpers; @@ -32,6 +33,7 @@ namespace Tapeti.Connection public override void HandleBasicDeliver(string consumerTag, ulong deliveryTag, bool redelivered, string exchange, string routingKey, IBasicProperties properties, byte[] body) { + ExceptionDispatchInfo exception = null; try { var message = dependencyResolver.Resolve().Deserialize(body, properties); @@ -81,19 +83,23 @@ namespace Tapeti.Connection if (!validMessageType) throw new ArgumentException($"Unsupported message type: {message.GetType().FullName}"); + + worker.Respond(deliveryTag, ConsumeResponse.Ack); } catch (Exception e) { - worker.Respond(deliveryTag, exceptionStrategy.HandleException(context, UnwrapException(e))); + exception = ExceptionDispatchInfo.Capture(UnwrapException(e)); + worker.Respond(deliveryTag, exceptionStrategy.HandleException(context, exception.SourceException)); } } - - worker.Respond(deliveryTag, ConsumeResponse.Ack); } catch (Exception e) { - worker.Respond(deliveryTag, exceptionStrategy.HandleException(null, UnwrapException(e))); + exception = ExceptionDispatchInfo.Capture(UnwrapException(e)); + worker.Respond(deliveryTag, exceptionStrategy.HandleException(null, exception.SourceException)); } + + exception?.Throw(); } @@ -103,11 +109,14 @@ namespace Tapeti.Connection // code using Tasks we have to unwrap these ourselves to get the proper // exception directly instead of "Errors occured". We might lose // some stack traces in the process though. - var aggregateException = exception as AggregateException; - if (aggregateException != null && aggregateException.InnerExceptions.Count == 1) - throw aggregateException.InnerExceptions[0]; + while (true) + { + var aggregateException = exception as AggregateException; + if (aggregateException == null || aggregateException.InnerExceptions.Count != 1) + return exception; - return UnwrapException(exception); + exception = aggregateException.InnerExceptions[0]; + } }