Include address in error message when address already in use (#1086).
This commit is contained in:
parent
f1f66448f4
commit
2c94884da9
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
|
@ -109,8 +110,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel
|
||||||
|
|
||||||
if (!parsedAddress.Host.Equals("localhost", StringComparison.OrdinalIgnoreCase))
|
if (!parsedAddress.Host.Equals("localhost", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
_disposables.Push(engine.CreateServer(
|
try
|
||||||
parsedAddress));
|
{
|
||||||
|
_disposables.Push(engine.CreateServer(parsedAddress));
|
||||||
|
}
|
||||||
|
catch (AggregateException ex)
|
||||||
|
{
|
||||||
|
if ((ex.InnerException as UvException)?.StatusCode == Constants.EADDRINUSE)
|
||||||
|
{
|
||||||
|
throw new IOException($"Failed to bind to address {parsedAddress}: address already in use.", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -120,24 +132,22 @@ namespace Microsoft.AspNetCore.Server.Kestrel
|
||||||
}
|
}
|
||||||
|
|
||||||
var ipv4Address = parsedAddress.WithHost("127.0.0.1");
|
var ipv4Address = parsedAddress.WithHost("127.0.0.1");
|
||||||
var exceptions = new List<UvException>();
|
var exceptions = new List<Exception>();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_disposables.Push(engine.CreateServer(ipv4Address));
|
_disposables.Push(engine.CreateServer(ipv4Address));
|
||||||
}
|
}
|
||||||
catch (AggregateException ex)
|
catch (AggregateException ex) when (ex.InnerException is UvException)
|
||||||
{
|
{
|
||||||
var uvException = ex.InnerException as UvException;
|
if ((ex.InnerException as UvException).StatusCode == Constants.EADDRINUSE)
|
||||||
|
|
||||||
if (uvException != null && uvException.StatusCode != Constants.EADDRINUSE)
|
|
||||||
{
|
{
|
||||||
_logger.LogWarning(0, ex, $"Unable to bind to {parsedAddress.ToString()} on the IPv4 loopback interface.");
|
throw new IOException($"Failed to bind to address {parsedAddress.ToString()} on the IPv4 loopback interface: port already in use.", ex);
|
||||||
exceptions.Add(uvException);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw;
|
_logger.LogWarning(0, ex, $"Unable to bind to {parsedAddress.ToString()} on the IPv4 loopback interface.");
|
||||||
|
exceptions.Add(ex.InnerException);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,26 +157,22 @@ namespace Microsoft.AspNetCore.Server.Kestrel
|
||||||
{
|
{
|
||||||
_disposables.Push(engine.CreateServer(ipv6Address));
|
_disposables.Push(engine.CreateServer(ipv6Address));
|
||||||
}
|
}
|
||||||
catch (AggregateException ex)
|
catch (AggregateException ex) when (ex.InnerException is UvException)
|
||||||
{
|
{
|
||||||
var uvException = ex.InnerException as UvException;
|
if ((ex.InnerException as UvException).StatusCode == Constants.EADDRINUSE)
|
||||||
|
|
||||||
if (uvException != null && uvException.StatusCode != Constants.EADDRINUSE)
|
|
||||||
{
|
{
|
||||||
_logger.LogWarning(0, ex, $"Unable to bind to {parsedAddress.ToString()} on the IPv6 loopback interface.");
|
throw new IOException($"Failed to bind to address {parsedAddress.ToString()} on the IPv6 loopback interface: port already in use.", ex);
|
||||||
exceptions.Add(uvException);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw;
|
_logger.LogWarning(0, ex, $"Unable to bind to {parsedAddress.ToString()} on the IPv6 loopback interface.");
|
||||||
|
exceptions.Add(ex.InnerException);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exceptions.Count == 2)
|
if (exceptions.Count == 2)
|
||||||
{
|
{
|
||||||
var ex = new AggregateException(exceptions);
|
throw new IOException($"Failed to bind to address {parsedAddress.ToString()}.", new AggregateException(exceptions));
|
||||||
_logger.LogError(0, ex, $"Unable to bind to {parsedAddress.ToString()} on any loopback interface.");
|
|
||||||
throw ex;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
|
|
@ -97,6 +98,49 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ThrowsWhenBindingToIPv4AddressInUse()
|
||||||
|
{
|
||||||
|
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||||
|
{
|
||||||
|
var port = GetNextPort();
|
||||||
|
socket.Bind(new IPEndPoint(IPAddress.Loopback, port));
|
||||||
|
|
||||||
|
var hostBuilder = new WebHostBuilder()
|
||||||
|
.UseKestrel()
|
||||||
|
.UseUrls($"http://127.0.0.1:{port}")
|
||||||
|
.Configure(ConfigureEchoAddress);
|
||||||
|
|
||||||
|
using (var host = hostBuilder.Build())
|
||||||
|
{
|
||||||
|
var exception = Assert.Throws<IOException>(() => host.Start());
|
||||||
|
Assert.Equal($"Failed to bind to address http://127.0.0.1:{port}: address already in use.", exception.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[ConditionalFact]
|
||||||
|
[IPv6SupportedCondition]
|
||||||
|
public void ThrowsWhenBindingToIPv6AddressInUse()
|
||||||
|
{
|
||||||
|
using (var socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp))
|
||||||
|
{
|
||||||
|
var port = GetNextPort();
|
||||||
|
socket.Bind(new IPEndPoint(IPAddress.IPv6Loopback, port));
|
||||||
|
|
||||||
|
var hostBuilder = new WebHostBuilder()
|
||||||
|
.UseKestrel()
|
||||||
|
.UseUrls($"http://[::1]:{port}")
|
||||||
|
.Configure(ConfigureEchoAddress);
|
||||||
|
|
||||||
|
using (var host = hostBuilder.Build())
|
||||||
|
{
|
||||||
|
var exception = Assert.Throws<IOException>(() => host.Start());
|
||||||
|
Assert.Equal($"Failed to bind to address http://[::1]:{port}: address already in use.", exception.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ThrowsWhenBindingLocalhostToIPv4AddressInUse()
|
public void ThrowsWhenBindingLocalhostToIPv4AddressInUse()
|
||||||
{
|
{
|
||||||
|
|
@ -138,8 +182,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
|
|
||||||
using (var host = hostBuilder.Build())
|
using (var host = hostBuilder.Build())
|
||||||
{
|
{
|
||||||
var exception = Assert.Throws<AggregateException>(() => host.Start());
|
var exception = Assert.Throws<IOException>(() => host.Start());
|
||||||
Assert.Contains(exception.InnerExceptions, ex => ex is UvException);
|
Assert.Equal(
|
||||||
|
$"Failed to bind to address http://localhost:{port} on the {(addressFamily == AddressFamily.InterNetwork ? "IPv4" : "IPv6")} loopback interface: port already in use.",
|
||||||
|
exception.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue