Compare commits

...

6 Commits

Author SHA1 Message Date
Marcel Hollerbach 4617ba2e93 eina_promise: do not self feedback when canceling
when canceling a all_promise it will cancel all futures. When that
happens, and one future is containing a promise, the value is unrolled,
and delivered as "Operation canceled" if this is happening to the last
future in all or any in race, the promise will then free its base ctx
which is already happening due to canceling.

With this this is not happening anymore.
2021-04-10 12:15:47 +02:00
Marcel Hollerbach c88f9abb40 efl_io_model: initialize memory
or this is causing trouble
2021-04-10 11:24:42 +02:00
Marcel Hollerbach 72a5388d6e efl_io_model: do not self reference, this is dangerous
what happened here is that people passed private data with a reference
to the object. Which is kind of a bad idea, as in some unthought of
conditions, events are forgot, which results in freeed memory beeing
accessed. This way its at least a error.
2021-04-10 11:23:05 +02:00
Marcel Hollerbach 79442c22af elm_genlist: ensure item is not deleted while beeing processed
the downside of doing things like genlist is doing, is that a object can
be deleted, due to the fact that the processing call does not have a eo
call in its stack trace, the object is not reffed at all. Hence it
simply gets deleted in the middle of beeing proceded.
With this, this is at least here not happening.
2021-04-10 10:44:54 +02:00
Marcel Hollerbach 9617cf1b85 Revert "wip"
This reverts commit c3cfa64d26.
2021-04-10 10:08:04 +02:00
Marcel Hollerbach c3cfa64d26 wip 2021-04-08 21:35:39 +02:00
4 changed files with 43 additions and 26 deletions

View File

@ -1148,6 +1148,7 @@ typedef struct _Base_Ctx {
Eina_Promise *promise;
Eina_Future **futures;
unsigned int futures_len;
Eina_Bool cancelled : 1;
} Base_Ctx;
typedef struct _All_Promise_Ctx {
@ -1173,6 +1174,7 @@ _base_ctx_clean(Base_Ctx *ctx)
static void
_all_promise_ctx_free(All_Promise_Ctx *ctx)
{
DBG("Cleaning base_ctx for %p", ctx);
_base_ctx_clean(&ctx->base);
eina_value_flush(&ctx->values);
free(ctx);
@ -1181,12 +1183,16 @@ _all_promise_ctx_free(All_Promise_Ctx *ctx)
static void
_all_promise_cancel(void *data, const Eina_Promise *dead EINA_UNUSED)
{
_all_promise_ctx_free(data);
All_Promise_Ctx *ctx = data;
ctx->base.cancelled = 1;
_all_promise_ctx_free(ctx);
}
static void
_race_promise_ctx_free(Race_Promise_Ctx *ctx)
{
DBG("Cleaning base_ctx for %p", ctx);
_base_ctx_clean(&ctx->base);
free(ctx);
}
@ -1194,6 +1200,9 @@ _race_promise_ctx_free(Race_Promise_Ctx *ctx)
static void
_race_promise_cancel(void *data, const Eina_Promise *dead EINA_UNUSED)
{
Race_Promise_Ctx *ctx = data;
ctx->base.cancelled = 1;
_race_promise_ctx_free(data);
}
@ -1233,7 +1242,8 @@ _race_then_cb(void *data, const Eina_Value v,
ctx->dispatching = EINA_TRUE;
//By freeing the race_ctx all the other futures will be cancelled.
_race_promise_ctx_free(ctx);
if (!ctx->base.cancelled)
_race_promise_ctx_free(ctx);
r = eina_value_struct_setup(&result, &RACE_STRUCT_DESC);
EINA_SAFETY_ON_FALSE_GOTO(r, err_setup);
@ -1275,7 +1285,8 @@ _all_then_cb(void *data, const Eina_Value v,
//We're in a safe context (from mainloop), so we can avoid scheduling a new dispatch
_eina_promise_clean_dispatch(ctx->base.promise, ctx->values);
ctx->values = EINA_VALUE_EMPTY; /* flushed in _eina_promise_clean_dispatch() */
_all_promise_ctx_free(ctx);
if (!ctx->base.cancelled)
_all_promise_ctx_free(ctx);
}
return v;
}

View File

@ -21,7 +21,7 @@
#define MY_CLASS_NAME "Efl_Io_Model"
static void _efl_io_model_info_free(Efl_Io_Model_Info *info, Eina_Bool model);
static void _efl_io_model_efl_model_monitor_add(Efl_Io_Model_Data *priv);
static void _efl_io_model_efl_model_monitor_add(const Eo *obj, Efl_Io_Model_Data *priv);
EINA_VALUE_STRUCT_DESC_DEFINE(_eina_file_direct_info_desc,
NULL,
@ -80,14 +80,17 @@ static Eina_Bool
_efl_model_evt_added_ecore_cb(void *data, int type, void *event)
{
Eio_Monitor_Event *ev = event;
Efl_Io_Model *obj;
Efl_Io_Model_Data *pd = data;
Efl_Model_Children_Event cevt;
Efl_Io_Model *obj = data;
Efl_Io_Model_Data *pd;
Efl_Model_Children_Event cevt = {0};
Efl_Io_Model_Info *mi;
Eina_List *l;
Eina_Stringshare *spath = NULL;
char *path = NULL;
pd = efl_data_scope_get(obj, EFL_IO_MODEL_CLASS);
EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EINA_TRUE);
if (type != EIO_MONITOR_DIRECTORY_CREATED && type != EIO_MONITOR_FILE_CREATED)
return EINA_TRUE;
@ -96,8 +99,6 @@ _efl_model_evt_added_ecore_cb(void *data, int type, void *event)
if (_already_added(pd, ev->filename))
return EINA_TRUE;
obj = pd->self;
path = ecore_file_dir_get(ev->filename);
if (!eina_streq(pd->path, path))
goto end;
@ -155,11 +156,10 @@ _efl_model_evt_added_ecore_cb(void *data, int type, void *event)
}
static void
_model_child_remove(Efl_Io_Model_Data *pd, Eina_Stringshare *path)
_model_child_remove(Efl_Io_Model *obj, Efl_Io_Model_Data *pd, Eina_Stringshare *path)
{
Efl_Io_Model_Info *mi;
Eina_List *l;
Efl_Io_Model *obj = pd->self;
Efl_Model_Children_Event cevt = { 0 };
unsigned int i = 0;
@ -191,16 +191,20 @@ static Eina_Bool
_efl_model_evt_deleted_ecore_cb(void *data, int type, void *event)
{
Eio_Monitor_Event *ev = event;
Efl_Io_Model_Data *pd = data;
Efl_Io_Model *obj = data;
Efl_Io_Model_Data *pd;
Eina_Stringshare *spath = NULL;
pd = efl_data_scope_get(obj, EFL_IO_MODEL_CLASS);
EINA_SAFETY_ON_FALSE_RETURN_VAL(pd, EINA_TRUE);
if (type != EIO_MONITOR_DIRECTORY_DELETED && type != EIO_MONITOR_FILE_DELETED)
return EINA_TRUE;
if (ev->monitor != pd->monitor) return EINA_TRUE;
spath = eina_stringshare_add(ev->filename);
_model_child_remove(pd, spath);
_model_child_remove(obj, pd, spath);
eina_stringshare_del(spath);
return EINA_TRUE;
@ -222,13 +226,17 @@ _eio_del_cleanup(Efl_Io_Model *obj)
static void
_eio_done_unlink_cb(void *data, Eio_File *handler EINA_UNUSED)
{
Efl_Io_Model *child = data;
Efl_Io_Model *child = data, *parent;
Efl_Io_Model_Data *child_pd, *pd;
parent = efl_parent_get(child);
EINA_SAFETY_ON_NULL_RETURN(parent);
child_pd = efl_data_scope_get(child, MY_CLASS);
pd = efl_data_scope_get(efl_parent_get(child), MY_CLASS);
EINA_SAFETY_ON_NULL_RETURN(child_pd);
pd = efl_data_scope_get(parent, MY_CLASS);
EINA_SAFETY_ON_NULL_RETURN(parent);
_model_child_remove(pd, child_pd->path);
_model_child_remove(parent, pd, child_pd->path);
_eio_del_cleanup(child);
}
@ -342,7 +350,7 @@ _eio_build_st_done(void *data, Eio_File *handler EINA_UNUSED, const Eina_Stat *s
if (eio_file_is_dir(pd->st))
{
// Now that we know we are a directory, we should whatch it
_efl_io_model_efl_model_monitor_add(pd);
_efl_io_model_efl_model_monitor_add(model, pd);
// And start listing its child
efl_model_children_count_get(model);
@ -861,7 +869,7 @@ _efl_io_model_efl_model_children_count_get(const Eo *obj, Efl_Io_Model_Data *pd)
//start monitoring before listing is done
//we will filter later on if we already published a file or not
_efl_io_model_efl_model_monitor_add(pd);
_efl_io_model_efl_model_monitor_add(obj, pd);
pd->request.listing = efl_future_then(obj, f,
.free = _efl_io_model_children_list_cleanup,
.data = pd);
@ -871,7 +879,7 @@ _efl_io_model_efl_model_children_count_get(const Eo *obj, Efl_Io_Model_Data *pd)
}
static void
_efl_io_model_efl_model_monitor_add(Efl_Io_Model_Data *priv)
_efl_io_model_efl_model_monitor_add(const Eo *obj, Efl_Io_Model_Data *priv)
{
if (!priv->monitor)
{
@ -881,11 +889,11 @@ _efl_io_model_efl_model_monitor_add(Efl_Io_Model_Data *priv)
for (i = 0; priv->mon.mon_event_child_add[i] != EIO_MONITOR_ERROR ; ++i)
priv->mon.ecore_child_add_handler[i] =
ecore_event_handler_add(priv->mon.mon_event_child_add[i], _efl_model_evt_added_ecore_cb, priv);
ecore_event_handler_add(priv->mon.mon_event_child_add[i], _efl_model_evt_added_ecore_cb, obj);
for (i = 0; priv->mon.mon_event_child_del[i] != EIO_MONITOR_ERROR ; ++i)
priv->mon.ecore_child_del_handler[i] =
ecore_event_handler_add(priv->mon.mon_event_child_del[i], _efl_model_evt_deleted_ecore_cb, priv);
ecore_event_handler_add(priv->mon.mon_event_child_del[i], _efl_model_evt_deleted_ecore_cb, obj);
}
}
@ -1059,8 +1067,6 @@ _efl_io_model_efl_object_finalize(Eo *obj, Efl_Io_Model_Data *pd)
pd->mon.mon_event_child_del[1] = EIO_MONITOR_FILE_DELETED;
pd->mon.mon_event_child_del[2] = EIO_MONITOR_ERROR;
pd->self = obj;
return obj;
}

View File

@ -35,8 +35,6 @@ struct _Efl_Io_Model_Info
struct _Efl_Io_Model_Data
{
Efl_Io_Model *self;
Eina_Stringshare *path;
Efl_Io_Model_Info *info;

View File

@ -4435,6 +4435,7 @@ _item_mouse_down_cb(void *data,
// NOTE: keep this code at the bottom, as the user can change the
// list at this point (clear, delete, etc...)
_item_highlight(it);
efl_ref(EO_OBJ(it));
if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
{
evas_object_smart_callback_call
@ -4443,7 +4444,8 @@ _item_mouse_down_cb(void *data,
(WIDGET(it), ELM_GENLIST_EVENT_ACTIVATED, eo_it);
}
evas_object_smart_callback_call
(WIDGET(it), "pressed", eo_it);
(WIDGET(it), "pressed", eo_it);
efl_unref(EO_OBJ(it));
}
static Item_Block *