From eaecfda35e7f19f9e00c0d788743abd25d5888bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6llner?= Date: Sun, 7 Jul 2019 17:12:49 +0200 Subject: [PATCH] See comments on issue #3: Pending questions shall fail when connection is broken. Adjusted required version of .NET Core runtime from 2.2 to 2.1 --- .../Capnp.Net.Runtime.Core21.csproj | 2 +- .../TcpRpcAdvancedStuff.cs | 34 ++++++++++++++++++- Capnp.Net.Runtime.Tests/TcpRpcInterop.cs | 29 ++++++++++++++-- Capnp.Net.Runtime/Rpc/RpcEngine.cs | 10 +++++- Capnp.Net.Runtime/Rpc/Vine.cs | 10 ++++-- 5 files changed, 77 insertions(+), 8 deletions(-) diff --git a/Capnp.Net.Runtime.Core21/Capnp.Net.Runtime.Core21.csproj b/Capnp.Net.Runtime.Core21/Capnp.Net.Runtime.Core21.csproj index 5381f55..909ef7f 100644 --- a/Capnp.Net.Runtime.Core21/Capnp.Net.Runtime.Core21.csproj +++ b/Capnp.Net.Runtime.Core21/Capnp.Net.Runtime.Core21.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp2.1 diff --git a/Capnp.Net.Runtime.Tests/TcpRpcAdvancedStuff.cs b/Capnp.Net.Runtime.Tests/TcpRpcAdvancedStuff.cs index ab161b1..12abb9c 100644 --- a/Capnp.Net.Runtime.Tests/TcpRpcAdvancedStuff.cs +++ b/Capnp.Net.Runtime.Tests/TcpRpcAdvancedStuff.cs @@ -10,7 +10,7 @@ using System.Threading.Tasks; namespace Capnp.Net.Runtime.Tests { [TestClass] - public class TcpRpcAdvancedStuff: TestBase + public class TcpRpcAdvancedStuff : TestBase { [TestMethod, Timeout(10000)] public void MultiConnect() @@ -88,5 +88,37 @@ namespace Capnp.Net.Runtime.Tests } } } + + [TestMethod, Timeout(10000)] + public void ClosingServerWhileRequestingBootstrap() + { + for (int i = 0; i < 100; i++) + { + var server = SetupServer(); + var counters = new Counters(); + var tcs = new TaskCompletionSource(); + server.Main = new TestInterfaceImpl(counters, tcs); + + using (var client = SetupClient()) + { + Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout)); + + using (var main = client.GetMain()) + { + server.Dispose(); + + // Resolution must either succeed or be cancelled. A hanging resolution would be inacceptable. + + try + { + Assert.IsTrue(((IResolvingCapability)main).WhenResolved.Wait(MediumNonDbgTimeout)); + } + catch (AggregateException) + { + } + } + } + } + } } } diff --git a/Capnp.Net.Runtime.Tests/TcpRpcInterop.cs b/Capnp.Net.Runtime.Tests/TcpRpcInterop.cs index 570d9c0..358bd31 100644 --- a/Capnp.Net.Runtime.Tests/TcpRpcInterop.cs +++ b/Capnp.Net.Runtime.Tests/TcpRpcInterop.cs @@ -751,7 +751,19 @@ namespace Capnp.Net.Runtime.Tests using (var main = client.GetMain()) { var resolving = main as IResolvingCapability; - if (!resolving.WhenResolved.Wait(MediumNonDbgTimeout)) + + bool success; + + try + { + success = resolving.WhenResolved.Wait(MediumNonDbgTimeout); + } + catch + { + success = false; + } + + if (!success) { if (++retry == 5) { @@ -917,13 +929,24 @@ namespace Capnp.Net.Runtime.Tests label: using (var client = new TcpRpcClient("localhost", TcpPort)) { - Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout)); using (var main = client.GetMain()) { var resolving = main as IResolvingCapability; - if (!resolving.WhenResolved.Wait(MediumNonDbgTimeout)) + + bool success; + + try + { + success = resolving.WhenResolved.Wait(MediumNonDbgTimeout); + } + catch + { + success = false; + } + + if (!success) { if (++retry == 5) { diff --git a/Capnp.Net.Runtime/Rpc/RpcEngine.cs b/Capnp.Net.Runtime/Rpc/RpcEngine.cs index 2546415..2333454 100644 --- a/Capnp.Net.Runtime/Rpc/RpcEngine.cs +++ b/Capnp.Net.Runtime/Rpc/RpcEngine.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; @@ -97,7 +98,14 @@ namespace Capnp.Rpc { _exportTable.Clear(); _revExportTable.Clear(); - _questionTable.Clear(); + + foreach (var question in _questionTable.Values.ToList()) + { + question.OnException(new RpcException("RPC connection is broken. Task would never return.")); + } + + Debug.Assert(_questionTable.Count == 0); + _answerTable.Clear(); _pendingDisembargos.Clear(); } diff --git a/Capnp.Net.Runtime/Rpc/Vine.cs b/Capnp.Net.Runtime/Rpc/Vine.cs index 7c661a3..feb3bde 100644 --- a/Capnp.Net.Runtime/Rpc/Vine.cs +++ b/Capnp.Net.Runtime/Rpc/Vine.cs @@ -38,9 +38,15 @@ namespace Capnp.Rpc { async void SetupCancellation() { - using (var registration = cancellationToken.Register(promisedAnswer.Dispose)) + try + { + using (var registration = cancellationToken.Register(promisedAnswer.Dispose)) + { + await promisedAnswer.WhenReturned; + } + } + catch { - await promisedAnswer.WhenReturned; } }