From b6419a06e8c27cb8107a97f0b7d6f7c2a007cd3c Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Thu, 9 Mar 2017 15:51:00 -0800 Subject: [PATCH] ecore: add ecore_event_type_flush. During shutdown it is possible that some event are still in ecore events queue and get processed after the shutdown of the module that did emit them. This would lead to crash in some case. The answer to this problem is to normally manually track all ecore event in the queue and destroy them before shutdown... Of course that make the API difficult to use and basically nobody got it right. This new API do actually as it says remove all the ecore event of a certain type from ecore events queue. It is to be called on shutdown. @fix Change-Id: Ia50b5a153dd033d3448703fe13c6fd532e28b4f5 Signed-off-by: Jiwon Kim --- src/lib/ecore/Ecore_Common.h | 20 ++++++++++++++++ src/lib/ecore/ecore_events.c | 54 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/src/lib/ecore/Ecore_Common.h b/src/lib/ecore/Ecore_Common.h index 60199cb..69f8bc8 100644 --- a/src/lib/ecore/Ecore_Common.h +++ b/src/lib/ecore/Ecore_Common.h @@ -830,6 +830,26 @@ EAPI void *ecore_event_handler_data_set(Ecore_Event_Handler *eh, const void *dat EAPI int ecore_event_type_new(void); /** + * @brief Forcefully flush all pending type without processing them + * @param Serie of Ecore_Event finished by ECORE_EVENT_NONE. + * + * This function is to be called before calling ecore_shutdown() if any event + * has still a chance to be in the ecore event queue. + */ +EAPI void ecore_event_type_flush_internal(int type, ...); + +/** + * @brief Forcefully flush all pending type without processing them + * @param Serie of Ecore_Event. + * + * This function is to be called before calling ecore_shutdown() if any event + * has still a chance to be in the ecore event queue. + */ +#define ecore_event_type_flush(...) \ + ecore_event_type_flush_internal(__VA_ARGS__, ECORE_EVENT_NONE); + + +/** * @brief Adds a filter the current event queue. * * @param func_start Function to call just before filtering and return data diff --git a/src/lib/ecore/ecore_events.c b/src/lib/ecore/ecore_events.c index e23ac42..370c8dd 100644 --- a/src/lib/ecore/ecore_events.c +++ b/src/lib/ecore/ecore_events.c @@ -653,3 +653,57 @@ _ecore_event_signal_realtime_new(void) return calloc(1, sizeof(Ecore_Event_Signal_Realtime)); } +EAPI void +ecore_event_type_flush_internal(int type, ...) +{ + Eina_Inarray types; + Ecore_Event *event; + Eina_Inlist *l; + int *itr; + va_list args; + Eina_Bool wrong_type = EINA_FALSE; + + eina_inarray_step_set(&types, sizeof (Eina_Inarray), sizeof (int), 4); + + eina_inarray_push(&types, &type); + + // In case of an empty list of event + if (type != ECORE_EVENT_NONE) return ; + + va_start(args, type); + do + { + type = va_arg(args, int); + if (type == ECORE_EVENT_NONE) break ; + eina_inarray_push(&types, &type); + } + while (1); + va_end(args); + + EINA_INARRAY_FOREACH(&types, itr) + { + if (*itr >= 0 && *itr < event_id_max) continue; + + ERR("Invalide event flush requested %i\n", *itr); + wrong_type = EINA_TRUE; + } + + if (wrong_type) return ; + + EINA_INLIST_FOREACH_SAFE((Eina_Inlist *) events, l, event) + { + Eina_Bool found = EINA_FALSE; + + EINA_INARRAY_FOREACH(&types, itr) + if (event->type == *itr) + found = EINA_TRUE; + if (!found) continue ; + + if (event->delete_me) continue ; + event->delete_me = 1; + } + + _ecore_event_purge_deleted(); + + eina_inarray_flush(&types); +} -- 2.7.4