Fix idlers when using recursive main loops.
authorbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 23 Feb 2010 21:27:04 +0000 (21:27 +0000)
committerbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 23 Feb 2010 21:27:04 +0000 (21:27 +0000)
commit2af66414676f112177a0e325e675fee00154d74d
tree7ab786e5e5efe462bb3b2f4090152af1c3ae60dc
parent89f27046600d92642803066c117a748a11028173
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;
}

git-svn-id: http://svn.enlightenment.org/svn/e/trunk/ecore@46406 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33
src/lib/ecore/ecore_idler.c