forked from enlightenment/efl
Eo: protect against recursive object destruction calls, fixes T1741
Summary: Eo: semantic obj->del replaced by obj->destructed Eo: protect against recursive object destruction calls Eo: add tests for bfada4b Reviewers: JackDanielZ, tasn Reviewed By: tasn Subscribers: cedric Maniphest Tasks: T1741 Differential Revision: https://phab.enlightenment.org/D1675 Fixes T1741 @fix
This commit is contained in:
parent
ee3bcaf71d
commit
18ceed4daf
|
@ -121,6 +121,7 @@ tests/eo/suite/eo_suite.h \
|
|||
tests/eo/suite/eo_error_msgs.h \
|
||||
tests/eo/suite/eo_error_msgs.c \
|
||||
tests/eo/suite/eo_test_class_errors.c \
|
||||
tests/eo/suite/eo_test_class_behaviour_errors.c \
|
||||
tests/eo/suite/eo_test_call_errors.c \
|
||||
tests/eo/suite/eo_test_general.c \
|
||||
tests/eo/suite/eo_test_value.c \
|
||||
|
|
|
@ -1855,7 +1855,7 @@ eo_destructed_is(const Eo *obj_id)
|
|||
{
|
||||
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, EINA_FALSE);
|
||||
|
||||
return obj->del;
|
||||
return obj->destructed;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
|
@ -1876,7 +1876,7 @@ eo_manual_free(Eo *obj_id)
|
|||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
if (!obj->del)
|
||||
if (!obj->destructed)
|
||||
{
|
||||
ERR("Tried deleting the object %p while still referenced(%d).", obj_id, obj->refcount);
|
||||
return EINA_FALSE;
|
||||
|
|
|
@ -104,7 +104,8 @@ struct _Eo_Object
|
|||
Eina_Bool finalized:1;
|
||||
|
||||
Eina_Bool composite:1;
|
||||
Eina_Bool del:1;
|
||||
Eina_Bool del_triggered:1;
|
||||
Eina_Bool destructed:1;
|
||||
Eina_Bool manual_free:1;
|
||||
};
|
||||
|
||||
|
@ -235,7 +236,7 @@ _eo_del_internal(const char *file, int line, _Eo_Object *obj)
|
|||
}
|
||||
}
|
||||
|
||||
obj->del = EINA_TRUE;
|
||||
obj->destructed = EINA_TRUE;
|
||||
obj->refcount--;
|
||||
}
|
||||
|
||||
|
@ -278,9 +279,16 @@ _eo_unref(_Eo_Object *obj)
|
|||
--(obj->refcount);
|
||||
if (obj->refcount == 0)
|
||||
{
|
||||
if (obj->del)
|
||||
if (obj->del_triggered)
|
||||
{
|
||||
ERR("Object %p already deleted.", obj);
|
||||
ERR("Object %p deletion already triggered. You wrongly call eo_unref() within a destructor.", obj);
|
||||
return;
|
||||
}
|
||||
obj->del_triggered = EINA_TRUE;
|
||||
|
||||
if (obj->destructed)
|
||||
{
|
||||
ERR("Object %p already destructed.", obj);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ static const Eo_Test_Case etc[] = {
|
|||
{ "Eo init", eo_test_init },
|
||||
{ "Eo general", eo_test_general },
|
||||
{ "Eo class errors", eo_test_class_errors },
|
||||
{ "Eo class behaviour errors", eo_test_class_behaviour_errors },
|
||||
{ "Eo call errors", eo_test_call_errors },
|
||||
{ "Eo eina value", eo_test_value },
|
||||
{ "Eo threaded eo calls", eo_test_threaded_calls },
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
void eo_test_init(TCase *tc);
|
||||
void eo_test_general(TCase *tc);
|
||||
void eo_test_class_errors(TCase *tc);
|
||||
void eo_test_class_behaviour_errors(TCase *tc);
|
||||
void eo_test_call_errors(TCase *tc);
|
||||
void eo_test_value(TCase *tc);
|
||||
void eo_test_threaded_calls(TCase *tc);
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Eo.h"
|
||||
#include "eo_suite.h"
|
||||
#include "eo_error_msgs.h"
|
||||
#include "eo_test_class_simple.h"
|
||||
|
||||
static struct log_ctx ctx;
|
||||
|
||||
const Eo_Class *klass;
|
||||
|
||||
static void _destructor_unref(Eo *obj, void *class_data EINA_UNUSED)
|
||||
{
|
||||
eo_do_super(obj, klass, eo_destructor());
|
||||
|
||||
/* this triggers an eo stack overflow if not correctly protected */
|
||||
eo_unref(obj);
|
||||
}
|
||||
|
||||
START_TEST(eo_destructor_unref)
|
||||
{
|
||||
eo_init();
|
||||
eina_log_print_cb_set(eo_test_print_cb, &ctx);
|
||||
|
||||
static Eo_Op_Description op_descs [] = {
|
||||
EO_OP_FUNC_OVERRIDE(eo_destructor, _destructor_unref),
|
||||
EO_OP_SENTINEL
|
||||
};
|
||||
|
||||
static Eo_Class_Description class_desc = {
|
||||
EO_VERSION,
|
||||
"Simple",
|
||||
EO_CLASS_TYPE_REGULAR,
|
||||
EO_CLASS_DESCRIPTION_OPS(op_descs),
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
klass = eo_class_new(&class_desc, SIMPLE_CLASS, NULL);
|
||||
fail_unless(klass);
|
||||
|
||||
Eo *obj = eo_add(klass, NULL);
|
||||
fail_unless(obj);
|
||||
|
||||
TEST_EO_ERROR("_eo_unref", "Object %p deletion already triggered. You wrongly call eo_unref() within a destructor.");
|
||||
eo_unref(obj);
|
||||
|
||||
eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
|
||||
|
||||
eo_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void eo_test_class_behaviour_errors(TCase *tc)
|
||||
{
|
||||
tcase_add_test(tc, eo_destructor_unref);
|
||||
}
|
Loading…
Reference in New Issue