From 20d9e486a8c20c9cc3f00d4c7627a0fd4a36885f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Fri, 5 Jul 2013 14:45:48 -0300 Subject: [PATCH] eldbus: Handle removal of last reference of connection inside of callback --- src/examples/eldbus/client.c | 20 ++++++++++++++++---- src/lib/eldbus/eldbus_core.c | 33 ++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/examples/eldbus/client.c b/src/examples/eldbus/client.c index 18a1fcdf3d..fe8391f579 100644 --- a/src/examples/eldbus/client.c +++ b/src/examples/eldbus/client.c @@ -12,6 +12,9 @@ static int _client_log_dom = -1; #define ERR(...) EINA_LOG_DOM_ERR(_client_log_dom, __VA_ARGS__) +static Eldbus_Connection *conn = NULL; +static Ecore_Timer *timeout = NULL; + static void _on_alive(void *context EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED) { @@ -53,7 +56,12 @@ test(void) static int n = 0; n++; if (n >= NTESTS) - printf("Passed in all tests\n"); + { + printf("Passed in all tests\nExiting...\n"); + eldbus_connection_unref(conn); + conn = NULL; + ecore_main_loop_quit(); + } else printf("Passed in %d/%d tests\n", n, NTESTS); } @@ -270,14 +278,15 @@ on_name_owner_changed(void *data EINA_UNUSED, const char *bus, const char *old_i static Eina_Bool finish(void *data EINA_UNUSED) { + ERR("Timeout\nSome error happened or server is taking too much time to respond."); ecore_main_loop_quit(); + timeout = NULL; return ECORE_CALLBACK_CANCEL; } int main(void) { - Eldbus_Connection *conn; Eldbus_Object *obj; Eldbus_Proxy *proxy; @@ -317,11 +326,14 @@ main(void) eldbus_name_owner_changed_callback_add(conn, BUS, on_name_owner_changed, conn, EINA_TRUE); - ecore_timer_add(30, finish, NULL); + timeout = ecore_timer_add(30, finish, NULL); ecore_main_loop_begin(); - eldbus_connection_unref(conn); + if (timeout) + ecore_timer_del(timeout); + if (conn) + eldbus_connection_unref(conn); eldbus_shutdown(); ecore_shutdown(); diff --git a/src/lib/eldbus/eldbus_core.c b/src/lib/eldbus/eldbus_core.c index 56fcd4038a..61ae802b38 100644 --- a/src/lib/eldbus/eldbus_core.c +++ b/src/lib/eldbus/eldbus_core.c @@ -756,26 +756,22 @@ static Eina_Bool eldbus_idler(void *data) { Eldbus_Connection *conn = data; - DBusConnection *dbus_conn; DBG("Connection@%p: Dispatch status: %d", conn, - dbus_connection_get_dispatch_status(conn->dbus_conn)); + dbus_connection_get_dispatch_status(conn->dbus_conn)); - if (DBUS_DISPATCH_COMPLETE == - dbus_connection_get_dispatch_status(conn->dbus_conn)) + if (dbus_connection_get_dispatch_status(conn->dbus_conn) == + DBUS_DISPATCH_COMPLETE) { DBG("Connection@%p: Dispatch complete, idler@%p finishing", - conn, conn->idler); + conn, conn->idler); conn->idler = NULL; return ECORE_CALLBACK_CANCEL; } - // make local copy of dbus_conn because something in dispatch can set - // conn->dbus_conn to NULL, thus losing our handle - dbus_conn = conn->dbus_conn; - dbus_connection_ref(dbus_conn); DBG("Connection@%p: Dispatching", conn); - dbus_connection_dispatch(dbus_conn); - dbus_connection_unref(dbus_conn); + eldbus_connection_ref(conn); + dbus_connection_dispatch(conn->dbus_conn); + eldbus_connection_unref(conn); return ECORE_CALLBACK_RENEW; } @@ -784,18 +780,24 @@ cb_dispatch_status(DBusConnection *dbus_conn EINA_UNUSED, DBusDispatchStatus new { Eldbus_Connection *conn = data; + if (!conn->refcount) + { + DBG("Connection[%p] being freed, dispatch blocked", conn); + return; + } + DBG("Connection@%p: Dispatch status: %d", conn, new_status); if ((new_status == DBUS_DISPATCH_DATA_REMAINS) && (!conn->idler)) { conn->idler = ecore_idler_add(eldbus_idler, conn); DBG("Connection@%p: Adding idler@%p to handle remaining dispatch data", - conn, conn->idler); + conn, conn->idler); } else if ((new_status != DBUS_DISPATCH_DATA_REMAINS) && (conn->idler)) { DBG("Connection@%p: No remaining dispatch data, clearing idler@%p", - conn, conn->idler); + conn, conn->idler); ecore_idler_del(conn->idler); conn->idler = NULL; @@ -1010,14 +1012,14 @@ _connection_get(Eldbus_Connection_Type type, const char *address) return NULL; } - eldbus_connection_setup(conn); conn->type = type; conn->refcount = 1; EINA_MAGIC_SET(conn, ELDBUS_CONNECTION_MAGIC); conn->names = eina_hash_string_superfast_new(NULL); + eldbus_connection_setup(conn); eldbus_signal_handler_add(conn, NULL, DBUS_PATH_LOCAL, DBUS_INTERFACE_LOCAL, - "Disconnected", _disconnected, conn); + "Disconnected", _disconnected, conn); obj = eldbus_object_get(conn, ELDBUS_FDO_BUS, ELDBUS_FDO_PATH); conn->fdo_proxy = eldbus_proxy_get(obj, ELDBUS_FDO_INTERFACE); @@ -1201,6 +1203,7 @@ _eldbus_connection_free(Eldbus_Connection *conn) } EINA_MAGIC_SET(conn, EINA_MAGIC_NONE); + //will trigger a cb_dispatch_status() dbus_connection_close(conn->dbus_conn); dbus_connection_unref(conn->dbus_conn); conn->dbus_conn = NULL;