diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/AddressRegistrationTests.cs b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/AddressRegistrationTests.cs index 27c5191b7d..5a605a74c6 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/AddressRegistrationTests.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/AddressRegistrationTests.cs @@ -505,32 +505,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests }); } - private static int _nextPort = 8001; - private static object _portLock = new object(); private static int GetNextPort() { - lock (_portLock) + using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) { - using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) - { - while (true) - { - try - { - var port = _nextPort++; - socket.Bind(new IPEndPoint(IPAddress.Loopback, port)); - return port; - } - catch (SocketException) - { - // Retry unless exhausted - if (_nextPort == 65536) - { - throw; - } - } - } - } + // Let the OS assign the next available port. Unless we cycle through all ports + // on a test run, the OS will always increment the port number when making these calls. + // This prevents races in parallel test runs where a test is already bound to + // a given port, and a new test is able to bind to the same port due to port + // reuse being enabled by default by the OS. + socket.Bind(new IPEndPoint(IPAddress.Loopback, 0)); + return ((IPEndPoint)socket.LocalEndPoint).Port; } }