From 00a1a203a5d6825460d83bd32ae43f8d88ec8d3f Mon Sep 17 00:00:00 2001 From: Lauro Moura Date: Mon, 1 Jul 2019 15:35:35 -0300 Subject: [PATCH] csharp: Fix Future callback lifetime Assigning a method directly to a field expecting a delegate creates a delegate on the fly. This delegate can be collected normally as any collectable object. In dotnet the GC is more aggressive, causing this delegate to be collected and C trying to call an invalid function. To avoid this, we create a static delegate that will be passed to C. Its lifetime will be tied to the static method it wraps. --- src/bindings/mono/eina_mono/eina_promises.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/bindings/mono/eina_mono/eina_promises.cs b/src/bindings/mono/eina_mono/eina_promises.cs index 34561a5b08..dc8642aeaa 100644 --- a/src/bindings/mono/eina_mono/eina_promises.cs +++ b/src/bindings/mono/eina_mono/eina_promises.cs @@ -295,12 +295,14 @@ public class Future private static IntPtr ThenRaw(IntPtr previous, ResolvedCb cb) { FutureDesc desc = new FutureDesc(); - desc.cb = NativeResolvedCb; + desc.cb = NativeResolvedCbDelegate; GCHandle handle = GCHandle.Alloc(cb); desc.data = GCHandle.ToIntPtr(handle); return eina_future_then_from_desc(previous, desc); } + private static FutureCb NativeResolvedCbDelegate = new FutureCb(NativeResolvedCb); + private static Eina.ValueNative NativeResolvedCb(IntPtr data, Eina.ValueNative value, IntPtr dead_future) { GCHandle handle = GCHandle.FromIntPtr(data); @@ -340,7 +342,7 @@ public class Future for (; i < cbsList.Count(); i++) { ResolvedCb cb = cbsList[i]; - descs[i].cb = NativeResolvedCb; + descs[i].cb = NativeResolvedCbDelegate; GCHandle handle = GCHandle.Alloc(cb); descs[i].data = GCHandle.ToIntPtr(handle); }