From fa3dff3165afaf37a3376aefcc6bcb17c9a1e854 Mon Sep 17 00:00:00 2001 From: raster Date: Fri, 7 Jan 2011 08:07:32 +0000 Subject: [PATCH] 1. fix potential bug in processing messages on a specific object where it could be deleted by callbacks 2. fix edje message process to only process messages from that obj - a bit complex as we need restart stuff too to handle the list becoming invalid. git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/edje@55973 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/lib/edje_message_queue.c | 69 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/src/lib/edje_message_queue.c b/src/lib/edje_message_queue.c index b8a5f20..9a4a339 100644 --- a/src/lib/edje_message_queue.c +++ b/src/lib/edje_message_queue.c @@ -6,6 +6,8 @@ static Ecore_Timer *_job_loss_timer = NULL; static Eina_List *msgq = NULL; static Eina_List *tmp_msgq = NULL; +static int tmp_msgq_processing = 0; +static int tmp_msgq_restart = 0; /*============================================================================* * API * @@ -97,6 +99,7 @@ edje_object_message_signal_process(Evas_Object *obj) Eina_List *l, *ln, *tmpq = NULL; Edje *ed; Edje_Message *em; + int gotos = 0; ed = _edje_fetch(obj); if (!ed) return; @@ -127,16 +130,70 @@ edje_object_message_signal_process(Evas_Object *obj) tmpq = NULL; } +#if 0 while (tmp_msgq) { Edje_Message *em; em = tmp_msgq->data; tmp_msgq = eina_list_remove_list(tmp_msgq, tmp_msgq); - em->edje->message.num--; - _edje_message_process(em); - _edje_message_free(em); + if (!ed->delete_me) + { + ed->processing_messages++; + _edje_message_process(em); + _edje_message_free(em); + ed->processing_messages--; + } + else + _edje_message_free(em); + } +#else + tmp_msgq_processing++; +again: + EINA_LIST_FOREACH_SAFE(tmp_msgq, l, ln, em) + { + if (em->edje != ed) continue; + tmp_msgq = eina_list_remove_list(tmp_msgq, tmp_msgq); + if (!ed->delete_me) + { + ed->processing_messages++; + _edje_message_process(em); + _edje_message_free(em); + ed->processing_messages--; + } + else + _edje_message_free(em); + if (ed->processing_messages == 0) + { + if (ed->delete_me) _edje_del(ed); + } + // if some child callback in _edje_message_process called + // edje_object_message_signal_process() or + // edje_message_signal_process() then those will mark the restart + // flag when they finish - it mabsicammyt means tmp_msgq and + // any item in it has potentially become invalid - so that means l + // and ln could be rogue pointers, so start again from the beginning + // and skip anything that is not this object and process only what is. + // to avoid self-feeding loops allow a max of 1024 loops. + if (tmp_msgq_restart) + { + tmp_msgq_restart = 0; + gotos++; + if (gotos < 1024) goto again; + else + { + WRN("Edje is in a self-feeding message loop (> 1024 gotos needed in a row)"); + goto end; + } + } } +end: + tmp_msgq_processing--; + if (tmp_msgq_processing == 0) + tmp_msgq_restart = 0; + else + tmp_msgq_restart = 1; +#endif } /** @@ -740,6 +797,7 @@ _edje_message_queue_process(void) msgq = NULL; } + tmp_msgq_processing++; while (tmp_msgq) { Edje_Message *em; @@ -763,6 +821,11 @@ _edje_message_queue_process(void) if (ed->delete_me) _edje_del(ed); } } + tmp_msgq_processing--; + if (tmp_msgq_processing == 0) + tmp_msgq_restart = 0; + else + tmp_msgq_restart = 1; } /* if the message queue filled again set a timer to expire in 0.0 sec */ -- 2.7.4