summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2017-09-28 11:27:56 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2017-09-29 10:28:41 +0900
commit7890d93c2e101e3c8892f81d36e62f064299a254 (patch)
treed7691b1e20c8fdad315c07c019a4e27fdd1d8163
parent2ae479a5e0770c3c85985af78c18f1f46ec90cd9 (diff)
downloadefl-7890d93c2e101e3c8892f81d36e62f064299a254.tar.gz
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
-rw-r--r--src/lib/efl/interfaces/efl_common_internal.h2
-rw-r--r--src/lib/evas/canvas/efl_input_event.eo11
-rw-r--r--src/lib/evas/canvas/efl_input_focus.c17
-rw-r--r--src/lib/evas/canvas/efl_input_hold.c12
-rw-r--r--src/lib/evas/canvas/efl_input_key.c7
-rw-r--r--src/lib/evas/canvas/efl_input_pointer.c10
-rw-r--r--src/lib/evas/canvas/evas_device.c23
-rw-r--r--src/lib/evas/canvas/evas_focus.c2
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)