jpeg pushed a commit to branch efl-1.20.

http://git.enlightenment.org/core/efl.git/commit/?id=7890d93c2e101e3c8892f81d36e62f064299a254

commit 7890d93c2e101e3c8892f81d36e62f064299a254
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Thu Sep 28 11:27:56 2017 +0900

    evas: Fix dangling references with input devices
    
    This solves issues with efl_input_dup() which didn't properly give a
    reference to the caller, resulting in dangling eo ids.
    
    Note: This may trigger leaks (instead of invalid refs), but this now
    actually reflects the meaning of @owned. This should work with bindings
    and C API users should know to call efl_unref().
    
    This patch is the reason for the previous improvements on eo_debug.
    
    @fix
---
 src/lib/efl/interfaces/efl_common_internal.h |  2 +-
 src/lib/evas/canvas/efl_input_event.eo       | 11 +++++++++--
 src/lib/evas/canvas/efl_input_focus.c        | 17 ++++++++++-------
 src/lib/evas/canvas/efl_input_hold.c         | 12 +++++++-----
 src/lib/evas/canvas/efl_input_key.c          |  7 ++++---
 src/lib/evas/canvas/efl_input_pointer.c      | 10 +++++-----
 src/lib/evas/canvas/evas_device.c            | 23 ++++++++++++++---------
 src/lib/evas/canvas/evas_focus.c             |  2 +-
 8 files changed, 51 insertions(+), 33 deletions(-)

diff --git a/src/lib/efl/interfaces/efl_common_internal.h 
b/src/lib/efl/interfaces/efl_common_internal.h
index cacb21a252..be6cd25957 100644
--- a/src/lib/efl/interfaces/efl_common_internal.h
+++ b/src/lib/efl/interfaces/efl_common_internal.h
@@ -114,7 +114,7 @@ struct _Efl_Input_Focus_Data
 {
    Eo *eo;
    Efl_Input_Device *device; //The seat
-   Eo *object; //The focused object - Efl.Canvas.Object or Efl.Canvas.
+   Eo *object_wref; // wref on the focused object - Efl.Canvas.Object or 
Efl.Canvas.
    double timestamp;
 };
 
diff --git a/src/lib/evas/canvas/efl_input_event.eo 
b/src/lib/evas/canvas/efl_input_event.eo
index 43f0753d75..56becac6cd 100644
--- a/src/lib/evas/canvas/efl_input_event.eo
+++ b/src/lib/evas/canvas/efl_input_event.eo
@@ -31,8 +31,15 @@ mixin Efl.Input.Event (Efl.Interface, Efl.Object)
          [[Resets the internal data to 0 or default values.]]
       }
       dup @pure_virtual {
-         [[Creates a copy of this event.]]
-         return: own(Efl.Input.Event); [[Event copy]]
+         [[Creates a copy of this event.
+
+           The returned event object is similar to the given object in most
+           ways except that @.fake will be $true.
+
+           Note: A reference is given to the caller. In order to avoid leaks
+           the C API users should call $efl_unref() after use.
+         ]]
+         return: own(Efl.Input.Event); [[Event copy, marked as @.fake.]]
       }
       @property device @pure_virtual {
          [[Input device that originated this event.]]
diff --git a/src/lib/evas/canvas/efl_input_focus.c 
b/src/lib/evas/canvas/efl_input_focus.c
index 5e3065b489..cc8e64aa0a 100644
--- a/src/lib/evas/canvas/efl_input_focus.c
+++ b/src/lib/evas/canvas/efl_input_focus.c
@@ -39,6 +39,7 @@ _del_hook(Eo *evt)
 static void
 _efl_input_focus_free(Efl_Input_Focus_Data *pd)
 {
+   efl_wref_del_safe(&pd->object_wref);
    efl_unref(pd->device);
 }
 
@@ -71,13 +72,13 @@ EOLIAN static void
 _efl_input_focus_object_set(Eo *obj EINA_UNUSED, Efl_Input_Focus_Data *pd,
                             Efl_Object *object)
 {
-   pd->object = object;
+   pd->object_wref = object;
 }
 
 EOLIAN static Efl_Object *
 _efl_input_focus_object_get(Eo *obj EINA_UNUSED, Efl_Input_Focus_Data *pd)
 {
-   return pd->object;
+   return pd->object_wref;
 }
 
 EOLIAN static void
@@ -111,18 +112,20 @@ _efl_input_focus_efl_input_event_timestamp_get(Eo *obj 
EINA_UNUSED,
 }
 
 EOLIAN static Efl_Input_Focus *
-_efl_input_focus_efl_input_event_dup(Eo *obj, Efl_Input_Focus_Data *pd)
+_efl_input_focus_efl_input_event_dup(Eo *obj EINA_UNUSED, Efl_Input_Focus_Data 
*pd)
 {
    Efl_Input_Focus_Data *ev;
    Efl_Input_Focus *evt;
 
-   evt = efl_input_instance_get(MY_CLASS, efl_parent_get(obj), (void **) &ev);
-   if (!evt || !ev) return NULL;
+   evt = efl_add(MY_CLASS, NULL);
+   ev = efl_data_scope_get(evt, MY_CLASS);
+   if (!ev) return NULL;
 
+   memcpy(ev, pd, sizeof(*ev));
    ev->eo        = evt;
-   ev->object    = pd->object;
    ev->device    = efl_ref(pd->device);
-   ev->timestamp = pd->timestamp;
+   efl_wref_add(ev->object_wref, &ev->object_wref);
+
    return evt;
 }
 
diff --git a/src/lib/evas/canvas/efl_input_hold.c 
b/src/lib/evas/canvas/efl_input_hold.c
index 1d991e78f0..beca304098 100644
--- a/src/lib/evas/canvas/efl_input_hold.c
+++ b/src/lib/evas/canvas/efl_input_hold.c
@@ -101,17 +101,19 @@ _efl_input_hold_efl_input_event_reset(Eo *obj, 
Efl_Input_Hold_Data *pd)
 }
 
 EOLIAN static Efl_Input_Event *
-_efl_input_hold_efl_input_event_dup(Eo *obj, Efl_Input_Hold_Data *pd)
+_efl_input_hold_efl_input_event_dup(Eo *obj EINA_UNUSED, Efl_Input_Hold_Data 
*pd)
 {
    Efl_Input_Hold_Data *ev;
-   Efl_Input_Event *evt = efl_add(EFL_INPUT_HOLD_CLASS, efl_parent_get(obj));
+   Efl_Input_Hold *evt;
+
+   evt = efl_add(MY_CLASS, NULL);
    ev = efl_data_scope_get(evt, MY_CLASS);
    if (!ev) return NULL;
 
+   memcpy(ev, pd, sizeof(*ev));
    ev->eo = evt;
-   ev->timestamp = pd->timestamp;
-   ev->data = pd->data;
-   ev->hold = pd->hold;
+   ev->legacy = NULL;
+   ev->evas_done = 0;
    ev->device = efl_ref(pd->device);
 
    return evt;
diff --git a/src/lib/evas/canvas/efl_input_key.c 
b/src/lib/evas/canvas/efl_input_key.c
index d4154ce963..052b971b3f 100644
--- a/src/lib/evas/canvas/efl_input_key.c
+++ b/src/lib/evas/canvas/efl_input_key.c
@@ -188,13 +188,14 @@ _efl_input_key_efl_input_event_reset(Eo *obj EINA_UNUSED, 
Efl_Input_Key_Data *pd
 }
 
 EOLIAN static Efl_Input_Event *
-_efl_input_key_efl_input_event_dup(Eo *obj, Efl_Input_Key_Data *pd)
+_efl_input_key_efl_input_event_dup(Eo *obj EINA_UNUSED, Efl_Input_Key_Data *pd)
 {
    Efl_Input_Key_Data *ev;
    Efl_Input_Key *evt;
 
-   evt = efl_input_instance_get(MY_CLASS, efl_parent_get(obj), (void **) &ev);
-   if (!evt || !ev) return NULL;
+   evt = efl_add(MY_CLASS, NULL);
+   ev = efl_data_scope_get(evt, MY_CLASS);
+   if (!ev) return NULL;
 
    memcpy(ev, pd, sizeof(*ev));
    ev->eo        = evt;
diff --git a/src/lib/evas/canvas/efl_input_pointer.c 
b/src/lib/evas/canvas/efl_input_pointer.c
index 5b720925f8..bc9708c32a 100644
--- a/src/lib/evas/canvas/efl_input_pointer.c
+++ b/src/lib/evas/canvas/efl_input_pointer.c
@@ -144,13 +144,14 @@ _efl_input_pointer_efl_input_event_reset(Eo *obj, 
Efl_Input_Pointer_Data *pd)
 }
 
 EOLIAN static Efl_Input_Event *
-_efl_input_pointer_efl_input_event_dup(Eo *obj, Efl_Input_Pointer_Data *pd)
+_efl_input_pointer_efl_input_event_dup(Eo *obj EINA_UNUSED, 
Efl_Input_Pointer_Data *pd)
 {
    Efl_Input_Pointer_Data *ev;
-   Efl_Input_Pointer *evt;
+   Efl_Input_Focus *evt;
 
-   evt = efl_input_instance_get(MY_CLASS, efl_parent_get(obj), (void **) &ev);
-   if (!evt) return NULL;
+   evt = efl_add(MY_CLASS, NULL);
+   ev = efl_data_scope_get(evt, MY_CLASS);
+   if (!ev) return NULL;
 
    memcpy(ev, pd, sizeof(*ev));
    ev->eo = evt;
@@ -158,7 +159,6 @@ _efl_input_pointer_efl_input_event_dup(Eo *obj, 
Efl_Input_Pointer_Data *pd)
    ev->evas_done = 0;
    ev->win_fed = 0;
    ev->fake = 1;
-   ev->legacy = NULL;
    ev->device = efl_ref(pd->device);
 
    return evt;
diff --git a/src/lib/evas/canvas/evas_device.c 
b/src/lib/evas/canvas/evas_device.c
index 7f93b77801..9c740c0e0a 100644
--- a/src/lib/evas/canvas/evas_device.c
+++ b/src/lib/evas/canvas/evas_device.c
@@ -460,7 +460,7 @@ evas_device_seat_id_get(const Evas_Device *dev)
 void
 _evas_device_cleanup(Evas *eo_e)
 {
-   Eina_List *cpy;
+   Eina_List *cpy, *deleted = NULL;
    Evas_Device *dev;
    Evas_Public_Data *e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
 
@@ -473,19 +473,26 @@ _evas_device_cleanup(Evas *eo_e)
      }
 
    /* If the device is deleted, _del_cb will remove the device
-      from the devices list. */
+    * from the devices list. Ensure we delete them only once, and only if this
+    * Evas is the owner, otherwise we would kill external references (eg.
+    * from efl_input_dup()). */
 again:
    e->devices_modified = EINA_FALSE;
    cpy = eina_list_clone(e->devices);
    EINA_LIST_FREE(cpy, dev)
      {
-        evas_device_del(dev);
-        if (e->devices_modified)
+        if (!eina_list_data_find(deleted, dev) && (efl_parent_get(dev) == 
eo_e))
           {
-             eina_list_free(cpy);
-             goto again;
+             evas_device_del(dev);
+             deleted = eina_list_append(deleted, dev);
+             if (e->devices_modified)
+               {
+                  eina_list_free(cpy);
+                  goto again;
+               }
           }
      }
+   eina_list_free(deleted);
 
    /* Not all devices were deleted. The user probably will unref them later.
       Since Evas will be deleted, remove the del callback from them and
@@ -493,9 +500,7 @@ again:
    */
    EINA_LIST_FREE(e->devices, dev)
      {
-        efl_event_callback_call(e->evas,
-                                EFL_CANVAS_EVENT_DEVICE_REMOVED,
-                                dev);
+        efl_event_callback_call(e->evas, EFL_CANVAS_EVENT_DEVICE_REMOVED, dev);
         efl_event_callback_del(dev, EFL_EVENT_DEL, _del_cb, e);
      }
 }
diff --git a/src/lib/evas/canvas/evas_focus.c b/src/lib/evas/canvas/evas_focus.c
index 6fc1ebaad2..17e38a4693 100644
--- a/src/lib/evas/canvas/evas_focus.c
+++ b/src/lib/evas/canvas/evas_focus.c
@@ -80,7 +80,7 @@ _evas_focus_dispatch_event(Evas_Object_Protected_Data *obj, 
Efl_Input_Device *se
    if (!evt) return;
 
    ev_data->device = efl_ref(seat);
-   ev_data->object = obj->object;
+   efl_wref_add(obj->object, &ev_data->object_wref);
    ev_data->timestamp = time(NULL);
 
    if (in)

-- 


Reply via email to