diff --git a/projects/RabbitMQ.Client/client/api/ShutdownEventArgs.cs b/projects/RabbitMQ.Client/client/api/ShutdownEventArgs.cs
index bf98a1882a..961c4a74ed 100644
--- a/projects/RabbitMQ.Client/client/api/ShutdownEventArgs.cs
+++ b/projects/RabbitMQ.Client/client/api/ShutdownEventArgs.cs
@@ -41,12 +41,14 @@ namespace RabbitMQ.Client
///
public class ShutdownEventArgs : EventArgs
{
+ private readonly Exception _exception;
+
///
/// Construct a with the given parameters and
/// 0 for and .
///
- public ShutdownEventArgs(ShutdownInitiator initiator, ushort replyCode, string replyText, object cause = null)
- : this(initiator, replyCode, replyText, 0, 0, cause)
+ public ShutdownEventArgs(ShutdownInitiator initiator, ushort replyCode, string replyText, object cause = null, Exception exception = null)
+ : this(initiator, replyCode, replyText, 0, 0, cause, exception)
{
}
@@ -54,7 +56,7 @@ public ShutdownEventArgs(ShutdownInitiator initiator, ushort replyCode, string r
/// Construct a with the given parameters.
///
public ShutdownEventArgs(ShutdownInitiator initiator, ushort replyCode, string replyText,
- ushort classId, ushort methodId, object cause = null)
+ ushort classId, ushort methodId, object cause = null, Exception exception = null)
{
Initiator = initiator;
ReplyCode = replyCode;
@@ -62,6 +64,25 @@ public ShutdownEventArgs(ShutdownInitiator initiator, ushort replyCode, string r
ClassId = classId;
MethodId = methodId;
Cause = cause;
+ _exception = exception;
+ }
+
+ ///
+ /// Exception causing the shutdown, or null if none.
+ ///
+ public Exception Exception
+ {
+ get
+ {
+ if (_exception != null)
+ {
+ return _exception;
+ }
+ else
+ {
+ return new Exception(ToString());
+ }
+ }
}
///
@@ -98,13 +119,14 @@ public ShutdownEventArgs(ShutdownInitiator initiator, ushort replyCode, string r
/// Override ToString to be useful for debugging.
///
public override string ToString()
- {
- return $"AMQP close-reason, initiated by {Initiator}"
+ {
+ return $"AMQP close-reason, initiated by {Initiator}"
+ $", code={ReplyCode}"
+ (ReplyText != null ? $", text='{ReplyText}'" : string.Empty)
+ $", classId={ClassId}"
+ $", methodId={MethodId}"
- + (Cause != null ? $", cause={Cause}" : string.Empty);
+ + (Cause != null ? $", cause={Cause}" : string.Empty)
+ + (_exception != null ? $", exception={_exception}" : string.Empty);
}
}
}
diff --git a/projects/RabbitMQ.Client/client/impl/Connection.cs b/projects/RabbitMQ.Client/client/impl/Connection.cs
index 8f315b8fc3..19d105c899 100644
--- a/projects/RabbitMQ.Client/client/impl/Connection.cs
+++ b/projects/RabbitMQ.Client/client/impl/Connection.cs
@@ -457,13 +457,14 @@ public void HandleMainLoopException(ShutdownEventArgs reason)
{
if (!SetCloseReason(reason))
{
- LogCloseError("Unexpected Main Loop Exception while closing: "
- + reason, new Exception(reason.ToString()));
+ LogCloseError($"Unexpected Main Loop Exception while closing: {reason}", reason.Exception);
return;
}
+ _model0.MaybeSetConnectionStartException(reason.Exception);
+
OnShutdown();
- LogCloseError($"Unexpected connection closure: {reason}", new Exception(reason.ToString()));
+ LogCloseError($"Unexpected connection closure: {reason}", reason.Exception);
}
public bool HardProtocolExceptionHandler(HardProtocolException hpe)
@@ -540,22 +541,33 @@ public void MainLoop()
catch (EndOfStreamException eose)
{
// Possible heartbeat exception
- HandleMainLoopException(new ShutdownEventArgs(
- ShutdownInitiator.Library,
- 0,
- "End of stream",
- eose));
+ var ea = new ShutdownEventArgs(ShutdownInitiator.Library,
+ 0, "End of stream",
+ cause: null, exception: eose);
+ HandleMainLoopException(ea);
}
catch (HardProtocolException hpe)
{
shutdownCleanly = HardProtocolExceptionHandler(hpe);
}
+ catch (FileLoadException fileLoadException)
+ {
+ /*
+ * https://github.com/rabbitmq/rabbitmq-dotnet-client/issues/1434
+ * Ensure that these exceptions eventually make it to application code
+ */
+ var ea = new ShutdownEventArgs(ShutdownInitiator.Library,
+ Constants.InternalError, fileLoadException.Message,
+ cause: null, exception: fileLoadException);
+ HandleMainLoopException(ea);
+ }
catch (Exception ex)
{
- HandleMainLoopException(new ShutdownEventArgs(ShutdownInitiator.Library,
+ var ea = new ShutdownEventArgs(ShutdownInitiator.Library,
Constants.InternalError,
- "Unexpected Exception",
- ex));
+ $"Unexpected Exception: {ex.Message}",
+ cause: null, exception: ex);
+ HandleMainLoopException(ea);
}
// If allowed for clean shutdown, run main loop until the
@@ -1104,7 +1116,8 @@ private void StartAndTune()
if (connectionStart == null)
{
- throw new IOException("connection.start was never received, likely due to a network timeout");
+ const string msg = "connection.start was never received, likely due to a network timeout";
+ throw new IOException(msg, _model0.ConnectionStartException);
}
ServerProperties = connectionStart.m_serverProperties;
diff --git a/projects/RabbitMQ.Client/client/impl/ModelBase.cs b/projects/RabbitMQ.Client/client/impl/ModelBase.cs
index 67f97f43bb..3bc28aacae 100644
--- a/projects/RabbitMQ.Client/client/impl/ModelBase.cs
+++ b/projects/RabbitMQ.Client/client/impl/ModelBase.cs
@@ -48,7 +48,9 @@ abstract class ModelBase : IFullModel, IRecoverable
{
///Only used to kick-start a connection open
///sequence. See
- public BlockingCell m_connectionStartCell = null;
+ internal BlockingCell m_connectionStartCell = null;
+ private Exception m_connectionStartException = null;
+
internal readonly IBasicProperties _emptyBasicProperties;
private readonly Dictionary _consumers = new Dictionary();
@@ -174,6 +176,19 @@ public bool IsOpen
public ISession Session { get; private set; }
+ public Exception ConnectionStartException
+ {
+ get { return m_connectionStartException; }
+ }
+
+ public void MaybeSetConnectionStartException(Exception ex)
+ {
+ if (m_connectionStartCell != null)
+ {
+ m_connectionStartException = ex;
+ }
+ }
+
public Task Close(ushort replyCode, string replyText, bool abort)
{
return Close(new ShutdownEventArgs(ShutdownInitiator.Application,
diff --git a/projects/Unit/APIApproval.Approve.verified.txt b/projects/Unit/APIApproval.Approve.verified.txt
index 044048d3be..fdfda01b15 100644
--- a/projects/Unit/APIApproval.Approve.verified.txt
+++ b/projects/Unit/APIApproval.Approve.verified.txt
@@ -609,10 +609,11 @@ namespace RabbitMQ.Client
}
public class ShutdownEventArgs : System.EventArgs
{
- public ShutdownEventArgs(RabbitMQ.Client.ShutdownInitiator initiator, ushort replyCode, string replyText, object cause = null) { }
- public ShutdownEventArgs(RabbitMQ.Client.ShutdownInitiator initiator, ushort replyCode, string replyText, ushort classId, ushort methodId, object cause = null) { }
+ public ShutdownEventArgs(RabbitMQ.Client.ShutdownInitiator initiator, ushort replyCode, string replyText, object cause = null, System.Exception exception = null) { }
+ public ShutdownEventArgs(RabbitMQ.Client.ShutdownInitiator initiator, ushort replyCode, string replyText, ushort classId, ushort methodId, object cause = null, System.Exception exception = null) { }
public object Cause { get; }
public ushort ClassId { get; }
+ public System.Exception Exception { get; }
public RabbitMQ.Client.ShutdownInitiator Initiator { get; }
public ushort MethodId { get; }
public ushort ReplyCode { get; }