eo: Fix deadlocks with composite objects

This happens with shared objects.

The situation seems to be:
1. object has composited object a of class A in thread 1
2. call something on object a from thread 2, deadlock
In fact, do anything from thread 2 on a shared object and you deadlock.
This commit is contained in:
Jean-Philippe Andre 2016-10-06 16:27:28 +09:00
parent 6ce60a0de5
commit 9c95eda748
3 changed files with 39 additions and 20 deletions

View File

@ -466,12 +466,11 @@ end:
Eo *emb_obj_id;
EINA_LIST_FOREACH(obj->composite_objects, itr, emb_obj_id)
{
_Eo_Object *emb_obj = _eo_obj_pointer_get((Eo_Id)emb_obj_id);
if (!emb_obj) continue;
EO_OBJ_POINTER(emb_obj_id, emb_obj);
if (EINA_UNLIKELY(!emb_obj)) continue;
func = _vtable_func_get(emb_obj->vtable, cache->op);
if (func == NULL) continue;
if (func == NULL) goto composite_continue;
if (EINA_LIKELY(func->func && func->src))
{
@ -481,8 +480,11 @@ end:
call->data = _efl_data_scope_get(emb_obj, func->src);
/* We reffed it above, but no longer need/use it. */
_efl_unref(obj);
EO_OBJ_DONE(emb_obj_id);
return EINA_TRUE;
}
composite_continue:
EO_OBJ_DONE(emb_obj_id);
}
}

View File

@ -1438,21 +1438,22 @@ _efl_object_event_global_freeze_count_get(Eo *klass EINA_UNUSED, void *pd EINA_U
EOLIAN static Eina_Bool
_efl_object_composite_attach(Eo *parent_id, Efl_Object_Data *pd EINA_UNUSED, Eo *comp_obj_id)
{
Eo *emb_obj_id = NULL;
EO_OBJ_POINTER_RETURN_VAL(comp_obj_id, comp_obj, EINA_FALSE);
EO_OBJ_POINTER(parent_id, parent);
// very unlikely so improve l1 instr cache by using goto
if (!parent) goto err_parent;
EO_OBJ_POINTER_GOTO(parent_id, parent, err_parent);
/* FIXME: composite should fail if domains are different */
/* Don't composite if we already have a composite object of this type */
{
Eina_List *itr;
Eo *emb_obj_id;
EINA_LIST_FOREACH(parent->composite_objects, itr, emb_obj_id)
{
EO_OBJ_POINTER_RETURN_VAL(emb_obj_id, emb_obj, EINA_FALSE);
// unlikely so improve l1 instr cache by using goto
if (emb_obj->klass == comp_obj->klass) goto err_klass;
EO_OBJ_POINTER_GOTO(emb_obj_id, emb_obj, err_klass);
if (EINA_UNLIKELY(emb_obj->klass == comp_obj->klass)) goto err_klass;
}
emb_obj_id = NULL;
}
Efl_Object_Data *comp_pd = efl_data_scope_get(comp_obj_id, EFL_OBJECT_CLASS);
@ -1466,11 +1467,13 @@ _efl_object_composite_attach(Eo *parent_id, Efl_Object_Data *pd EINA_UNUSED, Eo
parent->composite_objects = eina_list_prepend(parent->composite_objects, comp_obj_id);
if (emb_obj_id) EO_OBJ_DONE(emb_obj_id);
EO_OBJ_DONE(parent_id);
EO_OBJ_DONE(comp_obj_id);
return EINA_TRUE;
err_klass:
if (emb_obj_id) EO_OBJ_DONE(emb_obj_id);
EO_OBJ_DONE(parent_id);
err_parent:
EO_OBJ_DONE(comp_obj_id);
@ -1481,9 +1484,7 @@ EOLIAN static Eina_Bool
_efl_object_composite_detach(Eo *parent_id, Efl_Object_Data *pd EINA_UNUSED, Eo *comp_obj_id)
{
EO_OBJ_POINTER_RETURN_VAL(comp_obj_id, comp_obj, EINA_FALSE);
EO_OBJ_POINTER(parent_id, parent);
// very unlikely so improve l1 instr cache by using goto
if (!parent) goto err_parent;
EO_OBJ_POINTER_GOTO(parent_id, parent, err_parent);
// unlikely so improve l1 instr cache by using goto
if (!efl_composite_part_is(comp_obj_id)) goto err_part;

View File

@ -1371,7 +1371,7 @@ thr1(void *data, Eina_Thread t EINA_UNUSED)
{
Data *d = data;
Efl_Id_Domain dom;
Eo *objs2;
Eo *s1, *s2;
fail_if(efl_domain_switch(EFL_ID_DOMAIN_THREAD) != EINA_TRUE);
fail_if(efl_domain_get() != EFL_ID_DOMAIN_THREAD);
@ -1382,12 +1382,28 @@ thr1(void *data, Eina_Thread t EINA_UNUSED)
printf("VERIFY finalized_get()\n");
fail_if(!efl_finalized_get(d->objs));
printf("VERIFY parent_set(invalid)\n");
printf("VERIFY parent_set(invalid) -- WILL SHOW ERRORS\n");
efl_domain_current_push(EFL_ID_DOMAIN_SHARED);
objs2 = efl_add(DOMAIN_CLASS, NULL);
s1 = efl_add(DOMAIN_CLASS, NULL);
efl_domain_current_pop();
efl_del(objs2);
efl_parent_set(d->objs, objs2);
efl_del(s1);
efl_parent_set(d->objs, s1);
printf("END OF ERRORS\n");
printf("VERIFY composite\n");
efl_domain_current_push(EFL_ID_DOMAIN_SHARED);
s1 = efl_add(SIMPLE_CLASS, NULL, simple_a_set(efl_added, 7));
s2 = efl_add(SIMPLE_CLASS, NULL, simple_a_set(efl_added, 42));
efl_domain_current_pop();
efl_composite_attach(d->objs, s1);
int i1 = simple_a_get(d->objs);
int i2 = simple_a_get(s1);
fail_if(i1 != i2);
fail_if(efl_composite_attach(d->objs, s2));
efl_del(s1);
fail_if(!efl_composite_attach(d->objs, s2));
efl_del(s2);
printf("SET ON LOCAL\n");
domain_a_set(obj, 1234);
@ -1430,7 +1446,7 @@ thr1(void *data, Eina_Thread t EINA_UNUSED)
static void
_timeout(int val EINA_UNUSED)
{
printf("TIMED OUT!\n");
EINA_LOG_CRIT("TIMED OUT!");
exit(-1);
}
#endif