zehortigoza pushed a commit to branch master.
commit 20d9e486a8c20c9cc3f00d4c7627a0fd4a36885f
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/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 18a1fcd..fe8391f 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 56fcd40..61ae802 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;
--
------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:
Build for Windows Store.
http://p.sf.net/sfu/windows-dev2dev