AsyncResult
rethrows exceptions and NetTCP's SocketConnectionInitiator
does not throw relevant exceptions
#5697
Labels
Describe the bug
Many different types of connection issues are reported as "No IPEndpoints were found for host XYZ", including configuration issues (e.g. incorrect address) and other runtime issues (e.g. port exhaustion). This makes it incredibly difficult to debug, as relevant exceptions are either re-thrown, losing the stack trace, or completely swallowed by WCF and never thrown at all. I was able to track this down to 2 things:
1. AsyncResult
Here we can see async result re-throwing the exception from the IAsyncResult object, completely removing its stack trace.
wcf/src/System.ServiceModel.Primitives/src/Internals/System/Runtime/AsyncResult.cs
Lines 349 to 352 in ed1bd7a
2. SocketConnectionInitiator
Here we can see that at the the end of this method
if socketConnection == null
is checked first, beforeif lastException != null
. IfCreateConnectionAsync
throws an exception, of coursesocketConnection
will be null, and thusEndpointNotFoundException
will be thrown, rather than the exception throw byCreateConnectionAsync
. The important information insidelastException
which describes why the connection failed is never made available.wcf/src/System.ServiceModel.NetTcp/src/System/ServiceModel/Channels/SocketConnection.cs
Lines 937 to 986 in ed1bd7a
To Reproduce
GH-5697 MRP Projects.zip
I have attached some projects which you should add to the WCF solution in this repository. The WCF service is not important for this demonstration, it is just there to provide a service we can communicate with.
new Socket(...
, we will simulateConnectAsync
throwing an exception. Insert the following line of code:throw new SocketException((int)SocketError.NoBufferSpaceAvailable);
wcf/src/System.ServiceModel.NetTcp/src/System/ServiceModel/Channels/SocketConnection.cs
Line 816 in 1985f3c
EndpointNotFoundException
, which is completely useless. We know we should get an exception aboutNoBufferSpaceAvailable
. This exception is doubly useless since we have no idea where theEndpointNotFoundException
originally came from.That is all that is needed to reproduce. The below steps go into how I changed the Service Model code to get a useful exception at the call site.
AsyncResult
. This is where the re-throwing is happening. Replace it instead with ExceptionDispatchInfo to keep the existing stack trace:ExceptionDispatchInfo.Capture(Fx.Exception.AsError(asyncResult._exception)).Throw();
Note that an exception with anInnerException
could also be used.wcf/src/System.ServiceModel.Primitives/src/Internals/System/Runtime/AsyncResult.cs
Line 351 in 1985f3c
NoBufferSpaceAvailable
. We have more information in the trace and can see that SocketConnectionInitiator is the culprit.SocketConnectionInitiator.ConnectAsync
. In the WCF code, go to the below code, and swap the order of the if statements and their contents. That is,lastException != null
beforesocketConnection == null
.wcf/src/System.ServiceModel.NetTcp/src/System/ServiceModel/Channels/SocketConnection.cs
Lines 974 to 986 in 1985f3c
Please consider changing the code mentioned so that exceptions are made more easily available to developers for debugging purposes.
The text was updated successfully, but these errors were encountered: