efl/legacy/ecore/src/lib/ecore/ecore_idler.c

155 lines
3.5 KiB
C
Raw Normal View History

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include "Ecore.h"
#include "ecore_private.h"
struct _Ecore_Idler
{
EINA_INLIST;
ECORE_MAGIC;
Ecore_Task_Cb func;
void *data;
Fix idlers when using recursive main loops. If an idler created a recursive main loop (just called ecore_main_loop_begin()), then this recursive main loop should continue to process idlers from there and on, thus idler_current was added. When going back from recursion, the current iterator should be updated properly. This patch also fixes the deletion of idlers from recursive main loops by reference counting them. This way, the node will not be free()d inside inner loop cleanups and then crash when going back to outer loop. The following test case used to crash but not anymore: #include <Ecore.h> #include <Eina.h> static int _log_dom; #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__) static Ecore_Idler *handle; static int idler(void *data) { INF("idler"); return 1; } static int cb2(void *data) { INF("cb2 - delete cb1 handle"); ecore_idler_del(handle); ecore_main_loop_quit(); /* quits inner main loop */ return 0; } static int cb1(void *data) { INF("cb1: begin"); INF(" add cb2"); ecore_idler_add(cb2, NULL); INF(" inner main loop begin (recurse)"); ecore_main_loop_begin(); /* will it crash due ecore_idler_del(handle) * inside cb2()? It used to! */ INF("cb1: end"); ecore_main_loop_quit(); /* quits outer main loop */ return 0; } int main(void) { ecore_init(); _log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN); /* * Creating a new main loop from inside an idler callback, and inside * this new (inner) main loop deleting the caller callback used to * crash since the handle would be effectively free()d, but when the * recursion is over the pointer would be used. */ INF("main: begin"); handle = ecore_idler_add(cb1, NULL); ecore_idler_add(idler, NULL); ecore_main_loop_begin(); INF("main: end"); return 0; } SVN revision: 46406
2010-02-23 13:27:04 -08:00
int references;
Eina_Bool delete_me : 1;
};
static Ecore_Idler *idlers = NULL;
Fix idlers when using recursive main loops. If an idler created a recursive main loop (just called ecore_main_loop_begin()), then this recursive main loop should continue to process idlers from there and on, thus idler_current was added. When going back from recursion, the current iterator should be updated properly. This patch also fixes the deletion of idlers from recursive main loops by reference counting them. This way, the node will not be free()d inside inner loop cleanups and then crash when going back to outer loop. The following test case used to crash but not anymore: #include <Ecore.h> #include <Eina.h> static int _log_dom; #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__) static Ecore_Idler *handle; static int idler(void *data) { INF("idler"); return 1; } static int cb2(void *data) { INF("cb2 - delete cb1 handle"); ecore_idler_del(handle); ecore_main_loop_quit(); /* quits inner main loop */ return 0; } static int cb1(void *data) { INF("cb1: begin"); INF(" add cb2"); ecore_idler_add(cb2, NULL); INF(" inner main loop begin (recurse)"); ecore_main_loop_begin(); /* will it crash due ecore_idler_del(handle) * inside cb2()? It used to! */ INF("cb1: end"); ecore_main_loop_quit(); /* quits outer main loop */ return 0; } int main(void) { ecore_init(); _log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN); /* * Creating a new main loop from inside an idler callback, and inside * this new (inner) main loop deleting the caller callback used to * crash since the handle would be effectively free()d, but when the * recursion is over the pointer would be used. */ INF("main: begin"); handle = ecore_idler_add(cb1, NULL); ecore_idler_add(idler, NULL); ecore_main_loop_begin(); INF("main: end"); return 0; } SVN revision: 46406
2010-02-23 13:27:04 -08:00
static Ecore_Idler *idler_current = NULL;
static int idlers_delete_me = 0;
/**
* Add an idler handler.
2004-05-07 21:44:04 -07:00
* @param func The function to call when idling.
* @param data The data to be passed to this @p func call.
* @return A idler handle if successfully added. NULL otherwise.
* @ingroup Idle_Group
2006-12-27 19:31:44 -08:00
*
* Add an idler handle to the event loop, returning a handle on success and
* NULL otherwise. The function @p func will be called repeatedly while
* no other events are ready to be processed, as long as it returns 1
* (or ECORE_CALLBACK_RENEW). A return of 0 (or ECORE_CALLBACK_CANCEL) deletes
* the idler.
2006-12-27 19:31:44 -08:00
*
* Idlers are useful for progressively prossessing data without blocking.
*/
EAPI Ecore_Idler *
ecore_idler_add(Ecore_Task_Cb func, const void *data)
{
Ecore_Idler *ie;
if (!func) return NULL;
ie = calloc(1, sizeof(Ecore_Idler));
if (!ie) return NULL;
ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLER);
ie->func = func;
ie->data = (void *)data;
idlers = (Ecore_Idler *) eina_inlist_append(EINA_INLIST_GET(idlers), EINA_INLIST_GET(ie));
return ie;
}
/**
2004-05-07 21:44:04 -07:00
* Delete an idler callback from the list to be executed.
* @param idler The handle of the idler callback to delete
* @return The data pointer passed to the idler callback on success. NULL
* otherwise.
* @ingroup Idle_Group
*/
EAPI void *
ecore_idler_del(Ecore_Idler *idler)
{
if (!ECORE_MAGIC_CHECK(idler, ECORE_MAGIC_IDLER))
{
ECORE_MAGIC_FAIL(idler, ECORE_MAGIC_IDLER,
"ecore_idler_del");
return NULL;
}
EINA_SAFETY_ON_TRUE_RETURN_VAL(idler->delete_me, NULL);
idler->delete_me = 1;
idlers_delete_me = 1;
return idler->data;
}
void
_ecore_idler_shutdown(void)
{
Ecore_Idler *ie;
while ((ie = idlers))
{
idlers = (Ecore_Idler *) eina_inlist_remove(EINA_INLIST_GET(idlers), EINA_INLIST_GET(idlers));
ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
free(ie);
}
idlers_delete_me = 0;
Fix idlers when using recursive main loops. If an idler created a recursive main loop (just called ecore_main_loop_begin()), then this recursive main loop should continue to process idlers from there and on, thus idler_current was added. When going back from recursion, the current iterator should be updated properly. This patch also fixes the deletion of idlers from recursive main loops by reference counting them. This way, the node will not be free()d inside inner loop cleanups and then crash when going back to outer loop. The following test case used to crash but not anymore: #include <Ecore.h> #include <Eina.h> static int _log_dom; #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__) static Ecore_Idler *handle; static int idler(void *data) { INF("idler"); return 1; } static int cb2(void *data) { INF("cb2 - delete cb1 handle"); ecore_idler_del(handle); ecore_main_loop_quit(); /* quits inner main loop */ return 0; } static int cb1(void *data) { INF("cb1: begin"); INF(" add cb2"); ecore_idler_add(cb2, NULL); INF(" inner main loop begin (recurse)"); ecore_main_loop_begin(); /* will it crash due ecore_idler_del(handle) * inside cb2()? It used to! */ INF("cb1: end"); ecore_main_loop_quit(); /* quits outer main loop */ return 0; } int main(void) { ecore_init(); _log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN); /* * Creating a new main loop from inside an idler callback, and inside * this new (inner) main loop deleting the caller callback used to * crash since the handle would be effectively free()d, but when the * recursion is over the pointer would be used. */ INF("main: begin"); handle = ecore_idler_add(cb1, NULL); ecore_idler_add(idler, NULL); ecore_main_loop_begin(); INF("main: end"); return 0; } SVN revision: 46406
2010-02-23 13:27:04 -08:00
idler_current = NULL;
}
int
_ecore_idler_call(void)
{
Fix idlers when using recursive main loops. If an idler created a recursive main loop (just called ecore_main_loop_begin()), then this recursive main loop should continue to process idlers from there and on, thus idler_current was added. When going back from recursion, the current iterator should be updated properly. This patch also fixes the deletion of idlers from recursive main loops by reference counting them. This way, the node will not be free()d inside inner loop cleanups and then crash when going back to outer loop. The following test case used to crash but not anymore: #include <Ecore.h> #include <Eina.h> static int _log_dom; #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__) static Ecore_Idler *handle; static int idler(void *data) { INF("idler"); return 1; } static int cb2(void *data) { INF("cb2 - delete cb1 handle"); ecore_idler_del(handle); ecore_main_loop_quit(); /* quits inner main loop */ return 0; } static int cb1(void *data) { INF("cb1: begin"); INF(" add cb2"); ecore_idler_add(cb2, NULL); INF(" inner main loop begin (recurse)"); ecore_main_loop_begin(); /* will it crash due ecore_idler_del(handle) * inside cb2()? It used to! */ INF("cb1: end"); ecore_main_loop_quit(); /* quits outer main loop */ return 0; } int main(void) { ecore_init(); _log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN); /* * Creating a new main loop from inside an idler callback, and inside * this new (inner) main loop deleting the caller callback used to * crash since the handle would be effectively free()d, but when the * recursion is over the pointer would be used. */ INF("main: begin"); handle = ecore_idler_add(cb1, NULL); ecore_idler_add(idler, NULL); ecore_main_loop_begin(); INF("main: end"); return 0; } SVN revision: 46406
2010-02-23 13:27:04 -08:00
if (!idler_current)
{
/* regular main loop, start from head */
idler_current = idlers;
}
else
{
/* recursive main loop, continue from where we were */
idler_current = (Ecore_Idler *)EINA_INLIST_GET(idler_current)->next;
}
Fix idlers when using recursive main loops. If an idler created a recursive main loop (just called ecore_main_loop_begin()), then this recursive main loop should continue to process idlers from there and on, thus idler_current was added. When going back from recursion, the current iterator should be updated properly. This patch also fixes the deletion of idlers from recursive main loops by reference counting them. This way, the node will not be free()d inside inner loop cleanups and then crash when going back to outer loop. The following test case used to crash but not anymore: #include <Ecore.h> #include <Eina.h> static int _log_dom; #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__) static Ecore_Idler *handle; static int idler(void *data) { INF("idler"); return 1; } static int cb2(void *data) { INF("cb2 - delete cb1 handle"); ecore_idler_del(handle); ecore_main_loop_quit(); /* quits inner main loop */ return 0; } static int cb1(void *data) { INF("cb1: begin"); INF(" add cb2"); ecore_idler_add(cb2, NULL); INF(" inner main loop begin (recurse)"); ecore_main_loop_begin(); /* will it crash due ecore_idler_del(handle) * inside cb2()? It used to! */ INF("cb1: end"); ecore_main_loop_quit(); /* quits outer main loop */ return 0; } int main(void) { ecore_init(); _log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN); /* * Creating a new main loop from inside an idler callback, and inside * this new (inner) main loop deleting the caller callback used to * crash since the handle would be effectively free()d, but when the * recursion is over the pointer would be used. */ INF("main: begin"); handle = ecore_idler_add(cb1, NULL); ecore_idler_add(idler, NULL); ecore_main_loop_begin(); INF("main: end"); return 0; } SVN revision: 46406
2010-02-23 13:27:04 -08:00
while (idler_current)
{
Fix idlers when using recursive main loops. If an idler created a recursive main loop (just called ecore_main_loop_begin()), then this recursive main loop should continue to process idlers from there and on, thus idler_current was added. When going back from recursion, the current iterator should be updated properly. This patch also fixes the deletion of idlers from recursive main loops by reference counting them. This way, the node will not be free()d inside inner loop cleanups and then crash when going back to outer loop. The following test case used to crash but not anymore: #include <Ecore.h> #include <Eina.h> static int _log_dom; #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__) static Ecore_Idler *handle; static int idler(void *data) { INF("idler"); return 1; } static int cb2(void *data) { INF("cb2 - delete cb1 handle"); ecore_idler_del(handle); ecore_main_loop_quit(); /* quits inner main loop */ return 0; } static int cb1(void *data) { INF("cb1: begin"); INF(" add cb2"); ecore_idler_add(cb2, NULL); INF(" inner main loop begin (recurse)"); ecore_main_loop_begin(); /* will it crash due ecore_idler_del(handle) * inside cb2()? It used to! */ INF("cb1: end"); ecore_main_loop_quit(); /* quits outer main loop */ return 0; } int main(void) { ecore_init(); _log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN); /* * Creating a new main loop from inside an idler callback, and inside * this new (inner) main loop deleting the caller callback used to * crash since the handle would be effectively free()d, but when the * recursion is over the pointer would be used. */ INF("main: begin"); handle = ecore_idler_add(cb1, NULL); ecore_idler_add(idler, NULL); ecore_main_loop_begin(); INF("main: end"); return 0; } SVN revision: 46406
2010-02-23 13:27:04 -08:00
Ecore_Idler *ie = (Ecore_Idler *)idler_current;
if (!ie->delete_me)
{
Fix idlers when using recursive main loops. If an idler created a recursive main loop (just called ecore_main_loop_begin()), then this recursive main loop should continue to process idlers from there and on, thus idler_current was added. When going back from recursion, the current iterator should be updated properly. This patch also fixes the deletion of idlers from recursive main loops by reference counting them. This way, the node will not be free()d inside inner loop cleanups and then crash when going back to outer loop. The following test case used to crash but not anymore: #include <Ecore.h> #include <Eina.h> static int _log_dom; #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__) static Ecore_Idler *handle; static int idler(void *data) { INF("idler"); return 1; } static int cb2(void *data) { INF("cb2 - delete cb1 handle"); ecore_idler_del(handle); ecore_main_loop_quit(); /* quits inner main loop */ return 0; } static int cb1(void *data) { INF("cb1: begin"); INF(" add cb2"); ecore_idler_add(cb2, NULL); INF(" inner main loop begin (recurse)"); ecore_main_loop_begin(); /* will it crash due ecore_idler_del(handle) * inside cb2()? It used to! */ INF("cb1: end"); ecore_main_loop_quit(); /* quits outer main loop */ return 0; } int main(void) { ecore_init(); _log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN); /* * Creating a new main loop from inside an idler callback, and inside * this new (inner) main loop deleting the caller callback used to * crash since the handle would be effectively free()d, but when the * recursion is over the pointer would be used. */ INF("main: begin"); handle = ecore_idler_add(cb1, NULL); ecore_idler_add(idler, NULL); ecore_main_loop_begin(); INF("main: end"); return 0; } SVN revision: 46406
2010-02-23 13:27:04 -08:00
ie->references++;
if (!ie->func(ie->data))
{
if (!ie->delete_me) ecore_idler_del(ie);
}
Fix idlers when using recursive main loops. If an idler created a recursive main loop (just called ecore_main_loop_begin()), then this recursive main loop should continue to process idlers from there and on, thus idler_current was added. When going back from recursion, the current iterator should be updated properly. This patch also fixes the deletion of idlers from recursive main loops by reference counting them. This way, the node will not be free()d inside inner loop cleanups and then crash when going back to outer loop. The following test case used to crash but not anymore: #include <Ecore.h> #include <Eina.h> static int _log_dom; #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__) static Ecore_Idler *handle; static int idler(void *data) { INF("idler"); return 1; } static int cb2(void *data) { INF("cb2 - delete cb1 handle"); ecore_idler_del(handle); ecore_main_loop_quit(); /* quits inner main loop */ return 0; } static int cb1(void *data) { INF("cb1: begin"); INF(" add cb2"); ecore_idler_add(cb2, NULL); INF(" inner main loop begin (recurse)"); ecore_main_loop_begin(); /* will it crash due ecore_idler_del(handle) * inside cb2()? It used to! */ INF("cb1: end"); ecore_main_loop_quit(); /* quits outer main loop */ return 0; } int main(void) { ecore_init(); _log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN); /* * Creating a new main loop from inside an idler callback, and inside * this new (inner) main loop deleting the caller callback used to * crash since the handle would be effectively free()d, but when the * recursion is over the pointer would be used. */ INF("main: begin"); handle = ecore_idler_add(cb1, NULL); ecore_idler_add(idler, NULL); ecore_main_loop_begin(); INF("main: end"); return 0; } SVN revision: 46406
2010-02-23 13:27:04 -08:00
ie->references--;
}
Fix idlers when using recursive main loops. If an idler created a recursive main loop (just called ecore_main_loop_begin()), then this recursive main loop should continue to process idlers from there and on, thus idler_current was added. When going back from recursion, the current iterator should be updated properly. This patch also fixes the deletion of idlers from recursive main loops by reference counting them. This way, the node will not be free()d inside inner loop cleanups and then crash when going back to outer loop. The following test case used to crash but not anymore: #include <Ecore.h> #include <Eina.h> static int _log_dom; #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__) static Ecore_Idler *handle; static int idler(void *data) { INF("idler"); return 1; } static int cb2(void *data) { INF("cb2 - delete cb1 handle"); ecore_idler_del(handle); ecore_main_loop_quit(); /* quits inner main loop */ return 0; } static int cb1(void *data) { INF("cb1: begin"); INF(" add cb2"); ecore_idler_add(cb2, NULL); INF(" inner main loop begin (recurse)"); ecore_main_loop_begin(); /* will it crash due ecore_idler_del(handle) * inside cb2()? It used to! */ INF("cb1: end"); ecore_main_loop_quit(); /* quits outer main loop */ return 0; } int main(void) { ecore_init(); _log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN); /* * Creating a new main loop from inside an idler callback, and inside * this new (inner) main loop deleting the caller callback used to * crash since the handle would be effectively free()d, but when the * recursion is over the pointer would be used. */ INF("main: begin"); handle = ecore_idler_add(cb1, NULL); ecore_idler_add(idler, NULL); ecore_main_loop_begin(); INF("main: end"); return 0; } SVN revision: 46406
2010-02-23 13:27:04 -08:00
if (idler_current) /* may have changed in recursive main loops */
idler_current = (Ecore_Idler *)EINA_INLIST_GET(idler_current)->next;
}
if (idlers_delete_me)
{
Fix idlers when using recursive main loops. If an idler created a recursive main loop (just called ecore_main_loop_begin()), then this recursive main loop should continue to process idlers from there and on, thus idler_current was added. When going back from recursion, the current iterator should be updated properly. This patch also fixes the deletion of idlers from recursive main loops by reference counting them. This way, the node will not be free()d inside inner loop cleanups and then crash when going back to outer loop. The following test case used to crash but not anymore: #include <Ecore.h> #include <Eina.h> static int _log_dom; #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__) static Ecore_Idler *handle; static int idler(void *data) { INF("idler"); return 1; } static int cb2(void *data) { INF("cb2 - delete cb1 handle"); ecore_idler_del(handle); ecore_main_loop_quit(); /* quits inner main loop */ return 0; } static int cb1(void *data) { INF("cb1: begin"); INF(" add cb2"); ecore_idler_add(cb2, NULL); INF(" inner main loop begin (recurse)"); ecore_main_loop_begin(); /* will it crash due ecore_idler_del(handle) * inside cb2()? It used to! */ INF("cb1: end"); ecore_main_loop_quit(); /* quits outer main loop */ return 0; } int main(void) { ecore_init(); _log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN); /* * Creating a new main loop from inside an idler callback, and inside * this new (inner) main loop deleting the caller callback used to * crash since the handle would be effectively free()d, but when the * recursion is over the pointer would be used. */ INF("main: begin"); handle = ecore_idler_add(cb1, NULL); ecore_idler_add(idler, NULL); ecore_main_loop_begin(); INF("main: end"); return 0; } SVN revision: 46406
2010-02-23 13:27:04 -08:00
Ecore_Idler *l;
int deleted_idlers_in_use = 0;
for (l = idlers; l;)
{
Fix idlers when using recursive main loops. If an idler created a recursive main loop (just called ecore_main_loop_begin()), then this recursive main loop should continue to process idlers from there and on, thus idler_current was added. When going back from recursion, the current iterator should be updated properly. This patch also fixes the deletion of idlers from recursive main loops by reference counting them. This way, the node will not be free()d inside inner loop cleanups and then crash when going back to outer loop. The following test case used to crash but not anymore: #include <Ecore.h> #include <Eina.h> static int _log_dom; #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__) static Ecore_Idler *handle; static int idler(void *data) { INF("idler"); return 1; } static int cb2(void *data) { INF("cb2 - delete cb1 handle"); ecore_idler_del(handle); ecore_main_loop_quit(); /* quits inner main loop */ return 0; } static int cb1(void *data) { INF("cb1: begin"); INF(" add cb2"); ecore_idler_add(cb2, NULL); INF(" inner main loop begin (recurse)"); ecore_main_loop_begin(); /* will it crash due ecore_idler_del(handle) * inside cb2()? It used to! */ INF("cb1: end"); ecore_main_loop_quit(); /* quits outer main loop */ return 0; } int main(void) { ecore_init(); _log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN); /* * Creating a new main loop from inside an idler callback, and inside * this new (inner) main loop deleting the caller callback used to * crash since the handle would be effectively free()d, but when the * recursion is over the pointer would be used. */ INF("main: begin"); handle = ecore_idler_add(cb1, NULL); ecore_idler_add(idler, NULL); ecore_main_loop_begin(); INF("main: end"); return 0; } SVN revision: 46406
2010-02-23 13:27:04 -08:00
Ecore_Idler *ie = l;
l = (Ecore_Idler *) EINA_INLIST_GET(l)->next;
if (ie->delete_me)
{
Fix idlers when using recursive main loops. If an idler created a recursive main loop (just called ecore_main_loop_begin()), then this recursive main loop should continue to process idlers from there and on, thus idler_current was added. When going back from recursion, the current iterator should be updated properly. This patch also fixes the deletion of idlers from recursive main loops by reference counting them. This way, the node will not be free()d inside inner loop cleanups and then crash when going back to outer loop. The following test case used to crash but not anymore: #include <Ecore.h> #include <Eina.h> static int _log_dom; #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__) static Ecore_Idler *handle; static int idler(void *data) { INF("idler"); return 1; } static int cb2(void *data) { INF("cb2 - delete cb1 handle"); ecore_idler_del(handle); ecore_main_loop_quit(); /* quits inner main loop */ return 0; } static int cb1(void *data) { INF("cb1: begin"); INF(" add cb2"); ecore_idler_add(cb2, NULL); INF(" inner main loop begin (recurse)"); ecore_main_loop_begin(); /* will it crash due ecore_idler_del(handle) * inside cb2()? It used to! */ INF("cb1: end"); ecore_main_loop_quit(); /* quits outer main loop */ return 0; } int main(void) { ecore_init(); _log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN); /* * Creating a new main loop from inside an idler callback, and inside * this new (inner) main loop deleting the caller callback used to * crash since the handle would be effectively free()d, but when the * recursion is over the pointer would be used. */ INF("main: begin"); handle = ecore_idler_add(cb1, NULL); ecore_idler_add(idler, NULL); ecore_main_loop_begin(); INF("main: end"); return 0; } SVN revision: 46406
2010-02-23 13:27:04 -08:00
if (ie->references)
{
deleted_idlers_in_use++;
continue;
}
idlers = (Ecore_Idler *) eina_inlist_remove(EINA_INLIST_GET(idlers), EINA_INLIST_GET(ie));
ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
free(ie);
}
}
Fix idlers when using recursive main loops. If an idler created a recursive main loop (just called ecore_main_loop_begin()), then this recursive main loop should continue to process idlers from there and on, thus idler_current was added. When going back from recursion, the current iterator should be updated properly. This patch also fixes the deletion of idlers from recursive main loops by reference counting them. This way, the node will not be free()d inside inner loop cleanups and then crash when going back to outer loop. The following test case used to crash but not anymore: #include <Ecore.h> #include <Eina.h> static int _log_dom; #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__) static Ecore_Idler *handle; static int idler(void *data) { INF("idler"); return 1; } static int cb2(void *data) { INF("cb2 - delete cb1 handle"); ecore_idler_del(handle); ecore_main_loop_quit(); /* quits inner main loop */ return 0; } static int cb1(void *data) { INF("cb1: begin"); INF(" add cb2"); ecore_idler_add(cb2, NULL); INF(" inner main loop begin (recurse)"); ecore_main_loop_begin(); /* will it crash due ecore_idler_del(handle) * inside cb2()? It used to! */ INF("cb1: end"); ecore_main_loop_quit(); /* quits outer main loop */ return 0; } int main(void) { ecore_init(); _log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN); /* * Creating a new main loop from inside an idler callback, and inside * this new (inner) main loop deleting the caller callback used to * crash since the handle would be effectively free()d, but when the * recursion is over the pointer would be used. */ INF("main: begin"); handle = ecore_idler_add(cb1, NULL); ecore_idler_add(idler, NULL); ecore_main_loop_begin(); INF("main: end"); return 0; } SVN revision: 46406
2010-02-23 13:27:04 -08:00
if (!deleted_idlers_in_use)
idlers_delete_me = 0;
}
if (idlers) return 1;
return 0;
}
int
_ecore_idler_exist(void)
{
if (idlers) return 1;
return 0;
}