From d775b58a630d6d0fd2ac2176df91bc1142a5276f Mon Sep 17 00:00:00 2001 From: Lauro Moura Date: Mon, 15 Apr 2019 14:09:49 -0300 Subject: [PATCH] csharp: Fix free_cb calling under dotnet. Summary: dotnet's GC seems to be more agressive, showing some issues that usually do not appear when running under Mono's. This commit uses for free_cb's the same scheme we already use for regular Eo refs, using a GC handle to keep the cleaning callback alive. Reviewers: vitor.sousa, felipealmeida, woohyun Reviewed By: vitor.sousa Subscribers: segfaultxavi, cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D8593 --- .../eolian/mono/function_pointer.hh | 2 +- src/bin/eolian_mono/eolian/mono/klass.hh | 6 +-- src/bindings/mono/efl_mono/efl_all.cs | 21 ++++++++++ src/bindings/mono/eina_mono/eina_accessor.cs | 2 +- src/bindings/mono/eina_mono/eina_array.cs | 2 +- src/bindings/mono/eina_mono/eina_binbuf.cs | 2 +- src/bindings/mono/eina_mono/eina_hash.cs | 2 +- src/bindings/mono/eina_mono/eina_inarray.cs | 2 +- src/bindings/mono/eina_mono/eina_iterator.cs | 2 +- src/bindings/mono/eina_mono/eina_strbuf.cs | 2 +- src/bindings/mono/eina_mono/eina_value.cs | 2 +- .../mono/eldbus_mono/eldbus_connection.cs | 2 +- .../mono/eldbus_mono/eldbus_message.cs | 2 +- .../mono/eldbus_mono/eldbus_object.cs | 2 +- src/bindings/mono/eldbus_mono/eldbus_proxy.cs | 2 +- src/bindings/mono/eo_mono/iwrapper.cs | 39 ++++++++++++------- 16 files changed, 61 insertions(+), 31 deletions(-) diff --git a/src/bin/eolian_mono/eolian/mono/function_pointer.hh b/src/bin/eolian_mono/eolian/mono/function_pointer.hh index e243ca744c..f724d8029e 100644 --- a/src/bin/eolian_mono/eolian/mono/function_pointer.hh +++ b/src/bin/eolian_mono/eolian/mono/function_pointer.hh @@ -84,7 +84,7 @@ struct function_pointer { << scope_tab << scope_tab << scope_tab << "}\n" << scope_tab << scope_tab << scope_tab << "else\n" << scope_tab << scope_tab << scope_tab << "{\n" - << scope_tab << scope_tab << scope_tab << scope_tab << "Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(this._cb_free_cb, this._cb_data);\n" + << scope_tab << scope_tab << scope_tab << scope_tab << "Efl.Eo.Globals.ThreadSafeFreeCbExec(this._cb_free_cb, this._cb_data);\n" << scope_tab << scope_tab << scope_tab << "}\n" << scope_tab << scope_tab << scope_tab << "this._cb_free_cb = null;\n" << scope_tab << scope_tab << scope_tab << "this._cb_data = IntPtr.Zero;\n" diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh index 236cc69759..329a1c297f 100644 --- a/src/bin/eolian_mono/eolian/mono/klass.hh +++ b/src/bin/eolian_mono/eolian/mono/klass.hh @@ -628,12 +628,12 @@ struct klass << scope_tab << scope_tab << scope_tab << "else\n" << scope_tab << scope_tab << scope_tab << "{\n" - << scope_tab << scope_tab << scope_tab << scope_tab << "Monitor.Enter(Efl.Eo.Config.InitLock);\n" - << scope_tab << scope_tab << scope_tab << scope_tab << "if (Efl.Eo.Config.Initialized)\n" + << scope_tab << scope_tab << scope_tab << scope_tab << "Monitor.Enter(Efl.All.InitLock);\n" + << scope_tab << scope_tab << scope_tab << scope_tab << "if (Efl.All.MainLoopInitialized)\n" << scope_tab << scope_tab << scope_tab << scope_tab << "{\n" << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "Efl.Eo.Globals.efl_mono_thread_safe_native_dispose(h, gcHandlePtr);\n" << scope_tab << scope_tab << scope_tab << scope_tab << "}\n\n" - << scope_tab << scope_tab << scope_tab << scope_tab << "Monitor.Exit(Efl.Eo.Config.InitLock);\n" + << scope_tab << scope_tab << scope_tab << scope_tab << "Monitor.Exit(Efl.All.InitLock);\n" << scope_tab << scope_tab << scope_tab << "}\n" << scope_tab << scope_tab << "}\n" << scope_tab << "}\n\n" diff --git a/src/bindings/mono/efl_mono/efl_all.cs b/src/bindings/mono/efl_mono/efl_all.cs index 70b9825b9d..9a49730093 100644 --- a/src/bindings/mono/efl_mono/efl_all.cs +++ b/src/bindings/mono/efl_mono/efl_all.cs @@ -43,6 +43,13 @@ public static class All { private static bool InitializedUi = false; + public static bool MainLoopInitialized { + get; + private set; + } + + public static readonly object InitLock = new object(); + public static void Init(Efl.Csharp.Components components = Efl.Csharp.Components.Basic) { Eina.Config.Init(); @@ -56,24 +63,38 @@ public static class All Efl.Ui.Config.Init(); InitializedUi = true; } + Monitor.Enter(InitLock); + MainLoopInitialized = true; + Monitor.Exit(InitLock); } /// Shutdowns all EFL subsystems. public static void Shutdown() { // Try to cleanup everything before actually shutting down. + Eina.Log.Debug("Calling GC before shutdown"); System.GC.Collect(); System.GC.WaitForPendingFinalizers(); + Monitor.Enter(InitLock); + MainLoopInitialized = false; + Monitor.Exit(InitLock); + if (InitializedUi) { + Eina.Log.Debug("Shutting down Elementary"); Efl.Ui.Config.Shutdown(); } + Eina.Log.Debug("Shutting down Eldbus"); eldbus.Config.Shutdown(); + Eina.Log.Debug("Shutting down Evas"); evas_shutdown(); + Eina.Log.Debug("Shutting down Ecore"); ecore_shutdown(); + Eina.Log.Debug("Shutting down Eo"); Efl.Eo.Config.Shutdown(); + Eina.Log.Debug("Shutting down Eina"); Eina.Config.Shutdown(); } } diff --git a/src/bindings/mono/eina_mono/eina_accessor.cs b/src/bindings/mono/eina_mono/eina_accessor.cs index d14a2039d5..bafbbd84fe 100644 --- a/src/bindings/mono/eina_mono/eina_accessor.cs +++ b/src/bindings/mono/eina_mono/eina_accessor.cs @@ -78,7 +78,7 @@ public class Accessor : IEnumerable, IDisposable } else { - Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eina_accessor_free, Handle); + Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_accessor_free, Handle); } Handle = IntPtr.Zero; } diff --git a/src/bindings/mono/eina_mono/eina_array.cs b/src/bindings/mono/eina_mono/eina_array.cs index afa73e9775..e3bd852e2b 100644 --- a/src/bindings/mono/eina_mono/eina_array.cs +++ b/src/bindings/mono/eina_mono/eina_array.cs @@ -155,7 +155,7 @@ public class Array : IEnumerable, IDisposable } else { - Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eina_array_free, h); + Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_array_free, h); } } } diff --git a/src/bindings/mono/eina_mono/eina_binbuf.cs b/src/bindings/mono/eina_mono/eina_binbuf.cs index 2ae04ec1bd..e5dc817085 100644 --- a/src/bindings/mono/eina_mono/eina_binbuf.cs +++ b/src/bindings/mono/eina_mono/eina_binbuf.cs @@ -109,7 +109,7 @@ public class Binbuf : IDisposable } else { - Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eina_binbuf_free, Handle); + Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_binbuf_free, Handle); } } } diff --git a/src/bindings/mono/eina_mono/eina_hash.cs b/src/bindings/mono/eina_mono/eina_hash.cs index d74c96970b..8b3c1e7db5 100644 --- a/src/bindings/mono/eina_mono/eina_hash.cs +++ b/src/bindings/mono/eina_mono/eina_hash.cs @@ -193,7 +193,7 @@ public class Hash : IEnumerable>, IDi } else { - Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eina_hash_free, h); + Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_hash_free, h); } } } diff --git a/src/bindings/mono/eina_mono/eina_inarray.cs b/src/bindings/mono/eina_mono/eina_inarray.cs index 8fbd89191c..c7f3151ac1 100644 --- a/src/bindings/mono/eina_mono/eina_inarray.cs +++ b/src/bindings/mono/eina_mono/eina_inarray.cs @@ -147,7 +147,7 @@ public class Inarray : IEnumerable, IDisposable } else { - Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eina_inarray_free, h); + Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_inarray_free, h); } } } diff --git a/src/bindings/mono/eina_mono/eina_iterator.cs b/src/bindings/mono/eina_mono/eina_iterator.cs index 75ca1b2785..05b5408606 100644 --- a/src/bindings/mono/eina_mono/eina_iterator.cs +++ b/src/bindings/mono/eina_mono/eina_iterator.cs @@ -79,7 +79,7 @@ public class Iterator : IEnumerable, IDisposable } else { - Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eina_iterator_free, h); + Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_iterator_free, h); } } } diff --git a/src/bindings/mono/eina_mono/eina_strbuf.cs b/src/bindings/mono/eina_mono/eina_strbuf.cs index 927a21da08..a538de0fd2 100644 --- a/src/bindings/mono/eina_mono/eina_strbuf.cs +++ b/src/bindings/mono/eina_mono/eina_strbuf.cs @@ -99,7 +99,7 @@ public class Strbuf : IDisposable } else { - Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eina_strbuf_free, Handle); + Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_strbuf_free, Handle); } Handle = IntPtr.Zero; diff --git a/src/bindings/mono/eina_mono/eina_value.cs b/src/bindings/mono/eina_mono/eina_value.cs index 3c9cb53ced..627c7cb343 100644 --- a/src/bindings/mono/eina_mono/eina_value.cs +++ b/src/bindings/mono/eina_mono/eina_value.cs @@ -1411,7 +1411,7 @@ public class Value : IDisposable, IComparable, IEquatable } else { - Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eina_value_free, this.Handle); + Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_value_free, this.Handle); } } diff --git a/src/bindings/mono/eldbus_mono/eldbus_connection.cs b/src/bindings/mono/eldbus_mono/eldbus_connection.cs index ea8a45f7a1..f88f0ac598 100644 --- a/src/bindings/mono/eldbus_mono/eldbus_connection.cs +++ b/src/bindings/mono/eldbus_mono/eldbus_connection.cs @@ -167,7 +167,7 @@ public class Connection : IDisposable } else { - Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eldbus_connection_unref, h); + Efl.Eo.Globals.ThreadSafeFreeCbExec(eldbus_connection_unref, h); } } } diff --git a/src/bindings/mono/eldbus_mono/eldbus_message.cs b/src/bindings/mono/eldbus_mono/eldbus_message.cs index eec9167d18..559c2f10b9 100644 --- a/src/bindings/mono/eldbus_mono/eldbus_message.cs +++ b/src/bindings/mono/eldbus_mono/eldbus_message.cs @@ -236,7 +236,7 @@ public class Message : IDisposable } else { - Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eldbus_message_unref, h); + Efl.Eo.Globals.ThreadSafeFreeCbExec(eldbus_message_unref, h); } } } diff --git a/src/bindings/mono/eldbus_mono/eldbus_object.cs b/src/bindings/mono/eldbus_mono/eldbus_object.cs index 136e8407ac..682fda6565 100644 --- a/src/bindings/mono/eldbus_mono/eldbus_object.cs +++ b/src/bindings/mono/eldbus_mono/eldbus_object.cs @@ -158,7 +158,7 @@ public class Object : System.IDisposable } else { - Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eldbus_object_unref, h); + Efl.Eo.Globals.ThreadSafeFreeCbExec(eldbus_object_unref, h); } } } diff --git a/src/bindings/mono/eldbus_mono/eldbus_proxy.cs b/src/bindings/mono/eldbus_mono/eldbus_proxy.cs index c8ac4d265a..f5eec40d43 100644 --- a/src/bindings/mono/eldbus_mono/eldbus_proxy.cs +++ b/src/bindings/mono/eldbus_mono/eldbus_proxy.cs @@ -117,7 +117,7 @@ public class Proxy : IDisposable } else { - Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eldbus_proxy_unref, h); + Efl.Eo.Globals.ThreadSafeFreeCbExec(eldbus_proxy_unref, h); } } } diff --git a/src/bindings/mono/eo_mono/iwrapper.cs b/src/bindings/mono/eo_mono/iwrapper.cs index 4f4181d244..503b71ad28 100644 --- a/src/bindings/mono/eo_mono/iwrapper.cs +++ b/src/bindings/mono/eo_mono/iwrapper.cs @@ -77,7 +77,7 @@ public class Globals efl_mono_thread_safe_efl_unref(IntPtr eo); [DllImport(efl.Libs.CustomExports)] public static extern void - efl_mono_thread_safe_free_cb_exec(EinaFreeCb free_cb, IntPtr cb_data); + efl_mono_thread_safe_free_cb_exec(IntPtr free_cb, IntPtr cb_data); [DllImport(efl.Libs.Eo)] public static extern IntPtr efl_class_name_get(IntPtr eo); @@ -653,6 +653,7 @@ public class Globals return ret; } + private static Efl.FreeGCHandleCb FreeGCHandleCallbackDelegate = new Efl.FreeGCHandleCb(FreeGCHandleCallback); public static void FreeGCHandleCallback(IntPtr gcHandlePtr) { try @@ -667,6 +668,7 @@ public class Globals } } + private static Efl.RemoveEventsCb RemoveEventsCallbackDelegate = new Efl.RemoveEventsCb(RemoveEventsCallback); public static void RemoveEventsCallback(IntPtr obj, IntPtr gcHandlePtr) { try @@ -696,7 +698,27 @@ public class Globals public static void SetNativeDisposeCallbacks() { - efl_mono_gchandle_callbacks_set(FreeGCHandleCallback, RemoveEventsCallback); + efl_mono_gchandle_callbacks_set(FreeGCHandleCallbackDelegate, RemoveEventsCallbackDelegate); + } + + public static void ThreadSafeFreeCbExec(EinaFreeCb cbFreeCb, IntPtr cbData) + { + EinaFreeCb cb = (IntPtr gcHandlePtr) => { + cbFreeCb(cbData); + GCHandle gcHandle = GCHandle.FromIntPtr(gcHandlePtr); + gcHandle.Free(); + }; + + Monitor.Enter(Efl.All.InitLock); + if (Efl.All.MainLoopInitialized) + { + IntPtr cbPtr = Marshal.GetFunctionPointerForDelegate(cb); + var handle = GCHandle.Alloc(cb); + var handlePtr = GCHandle.ToIntPtr(handle); + + efl_mono_thread_safe_free_cb_exec(cbPtr, handlePtr); + } + Monitor.Exit(Efl.All.InitLock); } } // Globals @@ -704,27 +726,14 @@ public class Globals public static class Config { - public static bool Initialized { - get; - private set; - } - - public static readonly object InitLock = new object(); - public static void Init() { Globals.efl_object_init(); - Monitor.Enter(InitLock); - Initialized = true; - Monitor.Exit(InitLock); Globals.SetNativeDisposeCallbacks(); } public static void Shutdown() { - Monitor.Enter(InitLock); - Initialized = false; - Monitor.Exit(InitLock); Globals.efl_object_shutdown(); } }