Skip to content

Commit 4cb93ed

Browse files
authored
Merge pull request #1438 from rabbitmq/rabbitmq-dotnet-client-1434
Pass exception back up to application code
2 parents 3b4b222 + ed7b4e6 commit 4cb93ed

File tree

4 files changed

+72
-21
lines changed

4 files changed

+72
-21
lines changed

projects/RabbitMQ.Client/client/api/ShutdownEventArgs.cs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,27 +41,48 @@ namespace RabbitMQ.Client
4141
/// </remarks>
4242
public class ShutdownEventArgs : EventArgs
4343
{
44+
private readonly Exception _exception;
45+
4446
/// <summary>
4547
/// Construct a <see cref="ShutdownEventArgs"/> with the given parameters and
4648
/// 0 for <see cref="ClassId"/> and <see cref="MethodId"/>.
4749
/// </summary>
48-
public ShutdownEventArgs(ShutdownInitiator initiator, ushort replyCode, string replyText, object cause = null)
49-
: this(initiator, replyCode, replyText, 0, 0, cause)
50+
public ShutdownEventArgs(ShutdownInitiator initiator, ushort replyCode, string replyText, object cause = null, Exception exception = null)
51+
: this(initiator, replyCode, replyText, 0, 0, cause, exception)
5052
{
5153
}
5254

5355
/// <summary>
5456
/// Construct a <see cref="ShutdownEventArgs"/> with the given parameters.
5557
/// </summary>
5658
public ShutdownEventArgs(ShutdownInitiator initiator, ushort replyCode, string replyText,
57-
ushort classId, ushort methodId, object cause = null)
59+
ushort classId, ushort methodId, object cause = null, Exception exception = null)
5860
{
5961
Initiator = initiator;
6062
ReplyCode = replyCode;
6163
ReplyText = replyText;
6264
ClassId = classId;
6365
MethodId = methodId;
6466
Cause = cause;
67+
_exception = exception;
68+
}
69+
70+
/// <summary>
71+
/// Exception causing the shutdown, or null if none.
72+
/// </summary>
73+
public Exception Exception
74+
{
75+
get
76+
{
77+
if (_exception != null)
78+
{
79+
return _exception;
80+
}
81+
else
82+
{
83+
return new Exception(ToString());
84+
}
85+
}
6586
}
6687

6788
/// <summary>
@@ -98,13 +119,14 @@ public ShutdownEventArgs(ShutdownInitiator initiator, ushort replyCode, string r
98119
/// Override ToString to be useful for debugging.
99120
/// </summary>
100121
public override string ToString()
101-
{
102-
return $"AMQP close-reason, initiated by {Initiator}"
122+
{
123+
return $"AMQP close-reason, initiated by {Initiator}"
103124
+ $", code={ReplyCode}"
104125
+ (ReplyText != null ? $", text='{ReplyText}'" : string.Empty)
105126
+ $", classId={ClassId}"
106127
+ $", methodId={MethodId}"
107-
+ (Cause != null ? $", cause={Cause}" : string.Empty);
128+
+ (Cause != null ? $", cause={Cause}" : string.Empty)
129+
+ (_exception != null ? $", exception={_exception}" : string.Empty);
108130
}
109131
}
110132
}

projects/RabbitMQ.Client/client/impl/Connection.cs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -457,13 +457,14 @@ public void HandleMainLoopException(ShutdownEventArgs reason)
457457
{
458458
if (!SetCloseReason(reason))
459459
{
460-
LogCloseError("Unexpected Main Loop Exception while closing: "
461-
+ reason, new Exception(reason.ToString()));
460+
LogCloseError($"Unexpected Main Loop Exception while closing: {reason}", reason.Exception);
462461
return;
463462
}
464463

464+
_model0.MaybeSetConnectionStartException(reason.Exception);
465+
465466
OnShutdown();
466-
LogCloseError($"Unexpected connection closure: {reason}", new Exception(reason.ToString()));
467+
LogCloseError($"Unexpected connection closure: {reason}", reason.Exception);
467468
}
468469

469470
public bool HardProtocolExceptionHandler(HardProtocolException hpe)
@@ -540,22 +541,33 @@ public void MainLoop()
540541
catch (EndOfStreamException eose)
541542
{
542543
// Possible heartbeat exception
543-
HandleMainLoopException(new ShutdownEventArgs(
544-
ShutdownInitiator.Library,
545-
0,
546-
"End of stream",
547-
eose));
544+
var ea = new ShutdownEventArgs(ShutdownInitiator.Library,
545+
0, "End of stream",
546+
cause: null, exception: eose);
547+
HandleMainLoopException(ea);
548548
}
549549
catch (HardProtocolException hpe)
550550
{
551551
shutdownCleanly = HardProtocolExceptionHandler(hpe);
552552
}
553+
catch (FileLoadException fileLoadException)
554+
{
555+
/*
556+
* https://github.com/rabbitmq/rabbitmq-dotnet-client/issues/1434
557+
* Ensure that these exceptions eventually make it to application code
558+
*/
559+
var ea = new ShutdownEventArgs(ShutdownInitiator.Library,
560+
Constants.InternalError, fileLoadException.Message,
561+
cause: null, exception: fileLoadException);
562+
HandleMainLoopException(ea);
563+
}
553564
catch (Exception ex)
554565
{
555-
HandleMainLoopException(new ShutdownEventArgs(ShutdownInitiator.Library,
566+
var ea = new ShutdownEventArgs(ShutdownInitiator.Library,
556567
Constants.InternalError,
557-
"Unexpected Exception",
558-
ex));
568+
$"Unexpected Exception: {ex.Message}",
569+
cause: null, exception: ex);
570+
HandleMainLoopException(ea);
559571
}
560572

561573
// If allowed for clean shutdown, run main loop until the
@@ -1104,7 +1116,8 @@ private void StartAndTune()
11041116

11051117
if (connectionStart == null)
11061118
{
1107-
throw new IOException("connection.start was never received, likely due to a network timeout");
1119+
const string msg = "connection.start was never received, likely due to a network timeout";
1120+
throw new IOException(msg, _model0.ConnectionStartException);
11081121
}
11091122

11101123
ServerProperties = connectionStart.m_serverProperties;

projects/RabbitMQ.Client/client/impl/ModelBase.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ abstract class ModelBase : IFullModel, IRecoverable
4848
{
4949
///<summary>Only used to kick-start a connection open
5050
///sequence. See <see cref="Connection.Open"/> </summary>
51-
public BlockingCell<ConnectionStartDetails> m_connectionStartCell = null;
51+
internal BlockingCell<ConnectionStartDetails> m_connectionStartCell = null;
52+
private Exception m_connectionStartException = null;
53+
5254
internal readonly IBasicProperties _emptyBasicProperties;
5355

5456
private readonly Dictionary<string, IBasicConsumer> _consumers = new Dictionary<string, IBasicConsumer>();
@@ -174,6 +176,19 @@ public bool IsOpen
174176

175177
public ISession Session { get; private set; }
176178

179+
public Exception ConnectionStartException
180+
{
181+
get { return m_connectionStartException; }
182+
}
183+
184+
public void MaybeSetConnectionStartException(Exception ex)
185+
{
186+
if (m_connectionStartCell != null)
187+
{
188+
m_connectionStartException = ex;
189+
}
190+
}
191+
177192
public Task Close(ushort replyCode, string replyText, bool abort)
178193
{
179194
return Close(new ShutdownEventArgs(ShutdownInitiator.Application,

projects/Unit/APIApproval.Approve.verified.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,10 +609,11 @@ namespace RabbitMQ.Client
609609
}
610610
public class ShutdownEventArgs : System.EventArgs
611611
{
612-
public ShutdownEventArgs(RabbitMQ.Client.ShutdownInitiator initiator, ushort replyCode, string replyText, object cause = null) { }
613-
public ShutdownEventArgs(RabbitMQ.Client.ShutdownInitiator initiator, ushort replyCode, string replyText, ushort classId, ushort methodId, object cause = null) { }
612+
public ShutdownEventArgs(RabbitMQ.Client.ShutdownInitiator initiator, ushort replyCode, string replyText, object cause = null, System.Exception exception = null) { }
613+
public ShutdownEventArgs(RabbitMQ.Client.ShutdownInitiator initiator, ushort replyCode, string replyText, ushort classId, ushort methodId, object cause = null, System.Exception exception = null) { }
614614
public object Cause { get; }
615615
public ushort ClassId { get; }
616+
public System.Exception Exception { get; }
616617
public RabbitMQ.Client.ShutdownInitiator Initiator { get; }
617618
public ushort MethodId { get; }
618619
public ushort ReplyCode { get; }

0 commit comments

Comments
 (0)