From b65093ab729fc89b894fff58d928bde0d95eb8a7 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Thu, 1 Mar 2018 12:36:23 +0900 Subject: DynamicSignal: Add Dispose to SignalInfo SignalInfo implements IDisposable to free GCHandle. https://bugzilla.gnome.org/show_bug.cgi?id=793982 --- sources/custom/DynamicSignal.cs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/sources/custom/DynamicSignal.cs b/sources/custom/DynamicSignal.cs index 4236158..b7a9458 100644 --- a/sources/custom/DynamicSignal.cs +++ b/sources/custom/DynamicSignal.cs @@ -69,12 +69,13 @@ namespace Gst } } - class SignalInfo + class SignalInfo : IDisposable { uint handlerId; IntPtr closure; Delegate registeredHandler; Type argsType; + GCHandle gch; public IntPtr Closure { get { @@ -112,11 +113,12 @@ namespace Gst } } - public SignalInfo (uint handlerId, IntPtr closure, Delegate registeredHandler) + public SignalInfo (uint handlerId, IntPtr closure, Delegate registeredHandler, GCHandle gch) { this.handlerId = handlerId; this.closure = closure; this.registeredHandler = registeredHandler; + this.gch = gch; if (!IsValidDelegate (registeredHandler)) throw new Exception ("Invalid delegate"); @@ -164,6 +166,13 @@ namespace Gst return true; } + public void Dispose () + { + registeredHandler = null; + gch.Free (); + GC.SuppressFinalize (this); + } + public static bool IsValidDelegate (Delegate d) { MethodInfo mi = d.Method; @@ -227,9 +236,10 @@ namespace Gst // Let's allocate 64bytes for the GClosure, it should be more than necessary. IntPtr closure = g_closure_new_simple (64, IntPtr.Zero); - g_closure_set_meta_marshal (closure, (IntPtr)GCHandle.Alloc (k), marshalHandler); + GCHandle gch = GCHandle.Alloc (k); + g_closure_set_meta_marshal (closure, (IntPtr)gch, marshalHandler); uint signalId = g_signal_connect_closure (o.Handle, name, closure, after); - SignalHandlers.Add (k, new SignalInfo (signalId, closure, handler)); + SignalHandlers.Add (k, new SignalInfo (signalId, closure, handler, gch)); } } @@ -242,6 +252,7 @@ namespace Gst if (newHandler == null || handler == null) { g_signal_handler_disconnect (o.Handle, si.HandlerId); SignalHandlers.Remove (k); + si.Dispose (); } else { si.RegisteredHandler = newHandler; } -- cgit v1.2.3