zehortigoza pushed a commit to branch master.

commit 8355d5fd06cb7768349aee03e6481b4d1b9c62a1
Author: José Roberto de Souza <[email protected]>
Date:   Fri Jul 5 14:45:48 2013 -0300

    eldbus: Handle removal of last reference of connection inside of callback
---
 src/examples/client.c | 20 ++++++++++++++++----
 src/lib/eldbus_core.c | 33 ++++++++++++++++++---------------
 2 files changed, 34 insertions(+), 19 deletions(-)

diff --git a/src/examples/client.c b/src/examples/client.c
index 18a1fcd..fe8391f 100644
--- a/src/examples/client.c
+++ b/src/examples/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_core.c b/src/lib/eldbus_core.c
index 56fcd40..61ae802 100644
--- a/src/lib/eldbus_core.c
+++ b/src/lib/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;

-- 

------------------------------------------------------------------------------
Get your SQL database under version control now!
Version control is standard for application code, but databases havent 
caught up. So what steps can you take to put your SQL databases under 
version control? Why should you start doing it? Read more to find out.
http://pubads.g.doubleclick.net/gampad/clk?id=49501711&iu=/4140/ostg.clktrk

Reply via email to