From 2ad89756e1022b04eec620f5018ebd75d31cab03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6llner?= Date: Sat, 22 Feb 2020 11:22:13 +0100 Subject: [PATCH] Improved robustness of TCP connection handling + test --- Capnp.Net.Runtime.Tests/TcpRpcInterop.cs | 22 ++++++++++++++++++++- Capnp.Net.Runtime.Tests/TestBase.cs | 25 +++++++++++++++++++++++- Capnp.Net.Runtime/Rpc/TcpRpcServer.cs | 12 +++++++++--- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/Capnp.Net.Runtime.Tests/TcpRpcInterop.cs b/Capnp.Net.Runtime.Tests/TcpRpcInterop.cs index 58c66bf..929e3d2 100644 --- a/Capnp.Net.Runtime.Tests/TcpRpcInterop.cs +++ b/Capnp.Net.Runtime.Tests/TcpRpcInterop.cs @@ -36,7 +36,7 @@ namespace Capnp.Net.Runtime.Tests Process _currentProcess; - void LaunchCompatTestProcess(string whichTest, Action test) + bool TryLaunchCompatTestProcess(string whichTest, Action test) { string myPath = Path.GetDirectoryName(typeof(TcpRpcInterop).Assembly.Location); string config; @@ -71,6 +71,12 @@ namespace Capnp.Net.Runtime.Tests "Problem after launching test process"); test(_currentProcess.StandardOutput); + + return true; + } + catch (AssertFailedException) + { + return false; } finally { @@ -85,6 +91,20 @@ namespace Capnp.Net.Runtime.Tests } } + void LaunchCompatTestProcess(string whichTest, Action test) + { + for (int retry = 0; retry < 5; retry++) + { + if (TryLaunchCompatTestProcess(whichTest, test)) + return; + + if (whichTest.StartsWith("server:")) + PrepareNextTest(); + } + + Assert.Fail("Problem after launching test process"); + } + void SendInput(string line) { _currentProcess.StandardInput.WriteLine(line); diff --git a/Capnp.Net.Runtime.Tests/TestBase.cs b/Capnp.Net.Runtime.Tests/TestBase.cs index afdf1e0..f34842b 100644 --- a/Capnp.Net.Runtime.Tests/TestBase.cs +++ b/Capnp.Net.Runtime.Tests/TestBase.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Net; +using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -21,7 +22,29 @@ namespace Capnp.Net.Runtime.Tests protected ILogger Logger { get; set; } protected TcpRpcClient SetupClient() => new TcpRpcClient("localhost", TcpPort); - protected TcpRpcServer SetupServer() => new TcpRpcServer(IPAddress.Any, TcpPort); + protected TcpRpcServer SetupServer() + { + int attempt = 0; + + while (true) + { + try + { + return new TcpRpcServer(IPAddress.Any, TcpPort); + } + catch (SocketException) + { + // If the TCP listening port is occupied by some other process, + // retry with a different one + + if (attempt == 5) + throw; + } + + IncrementTcpPort(); + ++attempt; + } + } protected (TcpRpcServer, TcpRpcClient) SetupClientServerPair() { diff --git a/Capnp.Net.Runtime/Rpc/TcpRpcServer.cs b/Capnp.Net.Runtime/Rpc/TcpRpcServer.cs index dcd05fc..7ee616a 100644 --- a/Capnp.Net.Runtime/Rpc/TcpRpcServer.cs +++ b/Capnp.Net.Runtime/Rpc/TcpRpcServer.cs @@ -284,7 +284,9 @@ namespace Capnp.Rpc _listener = new TcpListener(localAddr, port); _listener.ExclusiveAddressUse = false; - for (int retry = 0; retry < 5; retry++) + int attempt = 0; + + while (true) { try { @@ -293,9 +295,13 @@ namespace Capnp.Rpc } catch (SocketException socketException) { - Logger.LogWarning($"Failed to listen on port {port}, attempt {retry}: {socketException}"); - Thread.Sleep(10); + if (attempt == 5) + throw; + + Logger.LogWarning($"Failed to listen on port {port}, attempt {attempt}: {socketException}"); } + + ++attempt; } _acceptorThread = new Thread(AcceptClients);