runtime: HttpClient.GetAsync/PostAsync sets different error code on SocketException on Windows 7 when host could not be resolved

On all platforms except Windows 7 when host name could not be resolved we get HttpRequestException with inner SocketException with SocketException.SocketErrorCode set to SocketError.HostNotFound while on Windows 7 we get SocketErrorCode.NoData.

This is problematic in Wcf scenarios where they wrap our exception and would like to throw System.ServiceModel.EndpointNotFoundException but the inconsistency makes it more difficult.

Simple repro is (PostAsync has identical result):

var r = (new HttpClient()).GetAsync("http://nonexistenthostname/foo/bar").Result;
Here is the exact exception being thrown on Windows7
        System.AggregateException : One or more errors occurred. (The requested name is valid, but no data of the requested type was found)
        ---- System.Net.Http.HttpRequestException : The requested name is valid, but no data of the requested type was found
        -------- System.Net.Sockets.SocketException : The requested name is valid, but no data of the requested type was found
        Stack Trace:
           E:\A\_work\104\s\src\mscorlib\src\System\Threading\Tasks\future.cs(493,0): at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
           C:\Users\dotnet-bot\Desktop\src\corefx\src\System.Net.Http\tests\FunctionalTests\HttpClientHandlerTest.cs(3180,0): at System.Net.Http.Functional.Tests.HttpClientHandlerTest.HttpClientNonExistingHostnameTest()
           ----- Inner Stack Trace -----
           C:\Users\dotnet-bot\Desktop\src\corefx\src\System.Net.Http\src\System\Net\Http\SocketsHttpHandler\ConnectHelper.cs(86,0): at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
           E:\A\_work\104\s\src\mscorlib\shared\System\Threading\Tasks\ValueTask.cs(723,0): at System.Threading.Tasks.ValueTask`1.get_Result()
           C:\Users\dotnet-bot\Desktop\src\corefx\src\System.Net.Http\src\System\Net\Http\SocketsHttpHandler\HttpConnectionPool.cs(338,0): at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
           E:\A\_work\104\s\src\mscorlib\shared\System\Threading\Tasks\ValueTask.cs(723,0): at System.Threading.Tasks.ValueTask`1.get_Result()
           C:\Users\dotnet-bot\Desktop\src\corefx\src\System.Net.Http\src\System\Net\Http\SocketsHttpHandler\HttpConnectionPool.cs(480,0): at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask`1 creationTask)
           E:\A\_work\104\s\src\mscorlib\shared\System\Threading\Tasks\ValueTask.cs(723,0): at System.Threading.Tasks.ValueTask`1.get_Result()
           C:\Users\dotnet-bot\Desktop\src\corefx\src\System.Net.Http\src\System\Net\Http\SocketsHttpHandler\HttpConnectionPool.cs(271,0): at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
           C:\Users\dotnet-bot\Desktop\src\corefx\src\System.Net.Http\src\System\Net\Http\SocketsHttpHandler\RedirectHandler.cs(30,0): at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
           C:\Users\dotnet-bot\Desktop\src\corefx\src\System.Net.Http\src\System\Net\Http\HttpClient.cs(479,0): at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
           ----- Inner Stack Trace -----
           C:\Users\dotnet-bot\Desktop\src\corefx\src\System.Net.Http\src\System\Net\Http\SocketsHttpHandler\ConnectHelper.cs(67,0): at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)

cc: @mconnew @stephentoub @davidsh @karelz

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 16 (16 by maintainers)

Most upvoted comments

After researching this, it is valid for a SocketException to have SocketErrorCode of either HostNotFound or NoData values for “host not found” scenarios.

We actually test for this: https://github.com/dotnet/corefx/blob/2e82c748da654905e29609804393e028a06d78fa/src/System.Net.Sockets/tests/FunctionalTests/DnsEndPointTest.cs#L67

The recommendation is for WCF to change their code and add a check for SocketErrorCode.NoData in addition to their current check for SocketErrorCode.HostNotFound:

See: https://github.com/dotnet/wcf/blob/46f14d00bfaed9bcb3867e09073e9ac52592079c/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/HttpChannelHelpers.cs#L142

I do not expect 2.0 to have any special casing for different OS behavior.

It would have different behavior because .NET Core 2.0 would use a different HTTP stack (WinHTTP) on Windows.

If this ends up working ok on Win7 with .NET Core 2.0 but broken on Win7 with .NET Core 2.1, then this would be an app-compat behavior difference (due to using the new SocketsHttpHandler by default). So, we should consider that as part of triaging this issue.