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.
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))
{
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);
}
}
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);
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);
_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;
{
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);
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);
static void
_timeout(int val EINA_UNUSED)
{
- printf("TIMED OUT!\n");
+ EINA_LOG_CRIT("TIMED OUT!");
exit(-1);
}
#endif