edje: fix edje_part_helpers refcounting

Summary:
the reference from efl_reuse was forgotten & the parent relation was not
correctlty setted, which led to the fact that NOREF was never emitted.
This caused that thte object never really was destructed probebly, and
thus the del_interceptor_cb was not executed, and the object simply
leaked.

The test checks that those properties are correctly set, additionally a
error is printed in the efl code when a part has not the expected
reference properties. This also enforces errors when users are doing
wrong things with objects returned by efl_part.

Reviewers: ManMower, zmike

Reviewed By: zmike

Subscribers: cedric, #committers

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D6254
This commit is contained in:
Marcel Hollerbach 2018-06-10 16:30:07 +02:00
parent 03e0310a82
commit d1e1adf0bc
3 changed files with 38 additions and 0 deletions

View File

@ -91,6 +91,8 @@ _edje_ ## type ## _internal_proxy_get(Edje_Object *obj EINA_UNUSED, Edje *ed, Ed
else \
{ \
PROXY_STATIC_VAR(type) = NULL; \
efl_parent_set(proxy, ed->obj); \
efl_unref(proxy); /* efl_reuse gives us one additional reference, give this one up as we gave ownerwhip back to ed->obj */\
_edje_real_part_set(proxy, ed, rp, part); \
} \
__VA_ARGS__; \

View File

@ -96,6 +96,12 @@ efl_part(const Eo *obj, const char *name)
if (!r) return NULL;
efl_event_callback_add(r, EFL_EVENT_NOREF, _noref_death, NULL);
//ensure that the parts that we have here are never leaked
//by checking theire references and ownership details
EINA_SAFETY_ON_NULL_RETURN_VAL(efl_parent_get(r), r);
EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_ref_count(r) == 1, r);
___efl_auto_unref_set(r, EINA_TRUE);
return efl_ref(r);

View File

@ -1043,6 +1043,35 @@ EFL_START_TEST(edje_test_text_cursor)
}
EFL_END_TEST
EFL_START_TEST(edje_test_part_caching)
{
Evas *evas = EDJE_TEST_INIT_EVAS();
Evas_Object *ly, *o1, *global_p = NULL;
ly = efl_add(EFL_CANVAS_LAYOUT_CLASS, evas,
efl_file_set(efl_added, test_layout_get("test_swallows.edj"), "test_group")
);
for (int i = 0; i < 10; ++i)
{
Evas_Object *p;
p = efl_part(ly, "swallow");
o1 = efl_content_get(p);
if (global_p)
ck_assert_ptr_eq(global_p, p);
global_p = p;
ck_assert_int_eq(efl_ref_count(p), 1);
ck_assert_ptr_eq(efl_parent_get(p), NULL);
}
EDJE_TEST_FREE_EVAS();
}
EFL_END_TEST
void edje_test_edje(TCase *tc)
{
tcase_add_test(tc, edje_test_edje_init);
@ -1070,4 +1099,5 @@ void edje_test_edje(TCase *tc)
tcase_add_test(tc, edje_test_signals);
tcase_add_test(tc, edje_test_signal_callback_del_full);
tcase_add_test(tc, edje_test_text_cursor);
tcase_add_test(tc, edje_test_part_caching);
}