diff --git a/Capnp.Net.Runtime.Tests/Mock/TestCapImplementations.cs b/Capnp.Net.Runtime.Tests/Mock/TestCapImplementations.cs index 795d451..3c5093e 100644 --- a/Capnp.Net.Runtime.Tests/Mock/TestCapImplementations.cs +++ b/Capnp.Net.Runtime.Tests/Mock/TestCapImplementations.cs @@ -421,9 +421,12 @@ namespace Capnp.Net.Runtime.Tests.GenImpls public void Dispose() { _tcs?.TrySetResult(0); + Assert.IsFalse(IsDisposed); IsDisposed = true; + DisposeCallStack = Environment.StackTrace; } + public string DisposeCallStack { get; private set; } public bool IsDisposed { get; private set; } public virtual Task Foo(uint i, bool j, CancellationToken cancellationToken) @@ -836,6 +839,7 @@ namespace Capnp.Net.Runtime.Tests.GenImpls public void Dispose() { ClientToHold?.Dispose(); + ClientToHold = null; } public Task Echo(ITestCallOrder cap, CancellationToken cancellationToken_) diff --git a/Capnp.Net.Runtime.Tests/Testsuite.cs b/Capnp.Net.Runtime.Tests/Testsuite.cs index a888d65..77e0a59 100644 --- a/Capnp.Net.Runtime.Tests/Testsuite.cs +++ b/Capnp.Net.Runtime.Tests/Testsuite.cs @@ -311,7 +311,7 @@ namespace Capnp.Net.Runtime.Tests using (var claimer = Skeleton.Claim(cap)) { - var ftask = main.CallFoo(cap, default); + var ftask = main.CallFoo(Proxy.Share(cap), default); testbed.MustComplete(ftask); Assert.AreEqual("bar", ftask.Result); @@ -319,8 +319,8 @@ namespace Capnp.Net.Runtime.Tests testbed.MustComplete(ctask); Assert.AreEqual(1u, ctask.Result); - ftask1 = main.CallFoo(cap, default); - ftask2 = main.CallFoo(cap, default); + ftask1 = main.CallFoo(Proxy.Share(cap), default); + ftask2 = main.CallFoo(Proxy.Share(cap), default); } testbed.MustComplete(ftask1); @@ -804,18 +804,20 @@ namespace Capnp.Net.Runtime.Tests public static void ReexportSenderPromise(ITestbed testbed) { - var impl = new TestTailCallerImpl(new Counters()); - using (var main = testbed.ConnectMain(impl)) + var impl = new TestMoreStuffImpl(new Counters()); + using (var main = testbed.ConnectMain(impl)) { - var tcs = new TaskCompletionSource(); - using (var promise = Proxy.Share(tcs.Task.Eager(true))) + var tcs = new TaskCompletionSource(); + var tcsd = new TaskCompletionSource(); + using (var promise = tcs.Task.Eager(true)) { - var task1 = main.Foo(1, Proxy.Share(promise)); - var task2 = main.Foo(2, Proxy.Share(promise)); - var callee = new TestTailCalleeImpl(new Counters()); + var task1 = main.CallFooWhenResolved(Proxy.Share(promise)); + var task2 = main.CallFooWhenResolved(Proxy.Share(promise)); + var callee = new TestInterfaceImpl(new Counters(), tcsd); tcs.SetResult(callee); testbed.MustComplete(task1, task2); } + testbed.MustComplete(tcsd.Task); } } } diff --git a/Capnp.Net.Runtime.Tests/Util/TestBase.cs b/Capnp.Net.Runtime.Tests/Util/TestBase.cs index e40b7a1..5f13b70 100644 --- a/Capnp.Net.Runtime.Tests/Util/TestBase.cs +++ b/Capnp.Net.Runtime.Tests/Util/TestBase.cs @@ -161,7 +161,7 @@ namespace Capnp.Net.Runtime.Tests T ITestbed.ConnectMain(object main) { - return (T)main; + return Proxy.Share((T)main); } void ITestbed.FlushCommunication() diff --git a/Capnp.Net.Runtime/Rpc/PolySkeleton.cs b/Capnp.Net.Runtime/Rpc/PolySkeleton.cs index 17def26..c7762dd 100644 --- a/Capnp.Net.Runtime/Rpc/PolySkeleton.cs +++ b/Capnp.Net.Runtime/Rpc/PolySkeleton.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -54,7 +55,8 @@ namespace Capnp.Rpc /// protected override void Dispose(bool disposing) { - foreach (var cap in _ifmap.Values) + foreach (var cap in _ifmap.Values.Take(1)) + // releasing first skeleton is sufficient. Avoid double-Dispose! { cap.Relinquish(); } @@ -64,7 +66,7 @@ namespace Capnp.Rpc internal override void Bind(object impl) { - foreach (Skeleton skel in _ifmap.Values) + foreach (Skeleton skel in _ifmap.Values) { skel.Bind(impl); } diff --git a/Capnp.Net.Runtime/Rpc/Proxy.cs b/Capnp.Net.Runtime/Rpc/Proxy.cs index de67ab1..f82b6e0 100644 --- a/Capnp.Net.Runtime/Rpc/Proxy.cs +++ b/Capnp.Net.Runtime/Rpc/Proxy.cs @@ -154,14 +154,14 @@ namespace Capnp.Rpc { if (disposing) { - _consumedCap?.Release(); + _consumedCap.Release(); } else { // When called from the Finalizer, we must not throw. // But when reference counting goes wrong, ConsumedCapability.Release() will throw an InvalidOperationException. // The only option here is to suppress that exception. - try { _consumedCap?.Release(); } + try { _consumedCap.Release(); } catch { } }