forked from enlightenment/efl
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:
parent
6ce60a0de5
commit
9c95eda748
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue