Skip to content
This repository has been archived by the owner on May 25, 2020. It is now read-only.

Commit

Permalink
csharp: Fix Future callback lifetime
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
lauromoura committed Jul 1, 2019
1 parent e020e43 commit 3e28685
Showing 1 changed file with 4 additions and 2 deletions.
6 changes: 4 additions & 2 deletions src/bindings/mono/eina_mono/eina_promises.cs
Original file line number Diff line number Diff line change
Expand Up @@ -295,12 +295,14 @@ public Future Then(ResolvedCb cb)
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);
Expand Down Expand Up @@ -340,7 +342,7 @@ public Future Chain(IEnumerable<ResolvedCb> cbs)
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);
}
Expand Down

0 comments on commit 3e28685

Please sign in to comment.