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