aboutsummaryrefslogtreecommitdiffstats
path: root/src/bindings
diff options
context:
space:
mode:
authorVitor Sousa <vitorsousa@expertisesolutions.com.br>2019-04-05 19:59:34 -0300
committerVitor Sousa <vitorsousa@expertisesolutions.com.br>2019-04-05 19:59:47 -0300
commit7c28762f15f9935d5ca08ef87ee7ddfaf1df4815 (patch)
tree3b602d7fb867e91c202f262b7aaa215c8245856b /src/bindings
parentefl-csharp: fix resource deallocation causing errors everywhere (diff)
downloadefl-7c28762f15f9935d5ca08ef87ee7ddfaf1df4815.tar.gz
efl-csharp: fix crash when events trigger after C# object `Dispose`
Summary: Rework general event handling to check individually each event call, if the object is not alive then the event will not be propagated. WeakReferences (and lambdas capturing those WeakRefs) are used to ensure this. Dispose methods in object now take care of checking if efl libraries are still initialized and thread-safely unregister each event before performing an efl_unref on the Eo object. Event handling in C# is now centered around a single dictionary inside the object: `EoEvents`. C# event triggers now properly trigger events on C too. Standardize C# event-triggering methods names (remove underscores). Some diminished use of static memory due events no longer requiring static key objects to be registered/unregistered. Some fixing of white space generation for generated events. Depends on https://phab.enlightenment.org/D8431 Reviewers: lauromoura, felipealmeida, segfaultxavi Reviewed By: lauromoura Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D8564
Diffstat (limited to 'src/bindings')
-rw-r--r--src/bindings/mono/eo_mono/iwrapper.cs98
-rw-r--r--src/bindings/mono/eo_mono/workaround.cs2
2 files changed, 78 insertions, 22 deletions
diff --git a/src/bindings/mono/eo_mono/iwrapper.cs b/src/bindings/mono/eo_mono/iwrapper.cs
index 69adf045ce..1aab776f26 100644
--- a/src/bindings/mono/eo_mono/iwrapper.cs
+++ b/src/bindings/mono/eo_mono/iwrapper.cs
@@ -68,6 +68,12 @@ public class Globals
[DllImport(efl.Libs.Eo)] public static extern int
efl_ref_count(IntPtr eo);
[DllImport(efl.Libs.CustomExports)] public static extern void
+ efl_mono_gchandle_callbacks_set(Efl.FreeGCHandleCb freeGCHandleCb, Efl.RemoveEventsCb removeEventsCb);
+ [DllImport(efl.Libs.CustomExports)] public static extern void
+ efl_mono_native_dispose(IntPtr eo, IntPtr gcHandle);
+ [DllImport(efl.Libs.CustomExports)] public static extern void
+ efl_mono_thread_safe_native_dispose(IntPtr eo, IntPtr gcHandle);
+ [DllImport(efl.Libs.CustomExports)] public static extern void
efl_mono_thread_safe_efl_unref(IntPtr eo);
[DllImport(efl.Libs.CustomExports)] public static extern void
@@ -186,28 +192,14 @@ public class Globals
public delegate IntPtr dlerror_delegate();
[DllImport(efl.Libs.Evil)] public static extern IntPtr dlerror();
- public delegate bool efl_event_callback_priority_add_delegate(
- System.IntPtr obj,
- IntPtr desc,
- short priority,
- Efl.EventCb cb,
- System.IntPtr data);
- [DllImport(efl.Libs.Eo)] public static extern bool efl_event_callback_priority_add(
- System.IntPtr obj,
- IntPtr desc,
- short priority,
- Efl.EventCb cb,
- System.IntPtr data);
- public delegate bool efl_event_callback_del_delegate(
- System.IntPtr obj,
- IntPtr desc,
- Efl.EventCb cb,
- System.IntPtr data);
- [DllImport(efl.Libs.Eo)] public static extern bool efl_event_callback_del(
- System.IntPtr obj,
- IntPtr desc,
- Efl.EventCb cb,
- System.IntPtr data);
+ [DllImport(efl.Libs.Eo)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+ efl_event_callback_priority_add(IntPtr obj, IntPtr desc, short priority, IntPtr cb, IntPtr data);
+
+ [DllImport(efl.Libs.Eo)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+ efl_event_callback_del(IntPtr obj, IntPtr desc, IntPtr cb, IntPtr data);
+
+ [DllImport(efl.Libs.Eo)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+ efl_event_callback_call(IntPtr obj, IntPtr desc, IntPtr event_info);
public const int RTLD_NOW = 2;
@@ -625,17 +617,79 @@ public class Globals
return ret;
}
+
+ public static void FreeGCHandleCallback(IntPtr gcHandlePtr)
+ {
+ try
+ {
+ GCHandle gcHandle = GCHandle.FromIntPtr(gcHandlePtr);
+ gcHandle.Free();
+ }
+ catch (Exception e)
+ {
+ Eina.Log.Error(e.ToString());
+ Eina.Error.Set(Eina.Error.UNHANDLED_EXCEPTION);
+ }
+ }
+
+ public static void RemoveEventsCallback(IntPtr obj, IntPtr gcHandlePtr)
+ {
+ try
+ {
+ GCHandle gcHandle = GCHandle.FromIntPtr(gcHandlePtr);
+ var eoEvents = gcHandle.Target as Dictionary<(IntPtr desc, object evtDelegate), (IntPtr evtCallerPtr, Efl.EventCb evtCaller)>;
+ if (eoEvents == null)
+ {
+ Eina.Log.Error($"Invalid event dictionary [GCHandle pointer: {gcHandlePtr}]");
+ return;
+ }
+
+ foreach (var item in eoEvents)
+ {
+ if (!efl_event_callback_del(obj, item.Key.desc, item.Value.evtCallerPtr, IntPtr.Zero))
+ {
+ Eina.Log.Error($"Failed to remove event proxy for event {item.Key.desc} [cb: {item.Value.evtCallerPtr}]");
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Eina.Log.Error(e.ToString());
+ Eina.Error.Set(Eina.Error.UNHANDLED_EXCEPTION);
+ }
+ }
+
+ public static void SetNativeDisposeCallbacks()
+ {
+ efl_mono_gchandle_callbacks_set(FreeGCHandleCallback, RemoveEventsCallback);
+ }
+
} // 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();
}
}
diff --git a/src/bindings/mono/eo_mono/workaround.cs b/src/bindings/mono/eo_mono/workaround.cs
index 1ef9ef0aba..e32c921862 100644
--- a/src/bindings/mono/eo_mono/workaround.cs
+++ b/src/bindings/mono/eo_mono/workaround.cs
@@ -115,6 +115,8 @@ public struct EventDescription
};
public delegate void EventCb(System.IntPtr data, ref Event.NativeStruct evt);
+public delegate void FreeGCHandleCb(System.IntPtr gcHandle);
+public delegate void RemoveEventsCb(System.IntPtr obj, System.IntPtr gcHandle);
[StructLayout(LayoutKind.Sequential)]
public struct TextCursorCursor