forked from enlightenment/efl
eldbus: Handle removal of last reference of connection inside of callback
This commit is contained in:
parent
dadf38cb2f
commit
20d9e486a8
|
@ -12,6 +12,9 @@
|
||||||
static int _client_log_dom = -1;
|
static int _client_log_dom = -1;
|
||||||
#define ERR(...) EINA_LOG_DOM_ERR(_client_log_dom, __VA_ARGS__)
|
#define ERR(...) EINA_LOG_DOM_ERR(_client_log_dom, __VA_ARGS__)
|
||||||
|
|
||||||
|
static Eldbus_Connection *conn = NULL;
|
||||||
|
static Ecore_Timer *timeout = NULL;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_on_alive(void *context EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED)
|
_on_alive(void *context EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED)
|
||||||
{
|
{
|
||||||
|
@ -53,7 +56,12 @@ test(void)
|
||||||
static int n = 0;
|
static int n = 0;
|
||||||
n++;
|
n++;
|
||||||
if (n >= NTESTS)
|
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
|
else
|
||||||
printf("Passed in %d/%d tests\n", n, NTESTS);
|
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
|
static Eina_Bool
|
||||||
finish(void *data EINA_UNUSED)
|
finish(void *data EINA_UNUSED)
|
||||||
{
|
{
|
||||||
|
ERR("Timeout\nSome error happened or server is taking too much time to respond.");
|
||||||
ecore_main_loop_quit();
|
ecore_main_loop_quit();
|
||||||
|
timeout = NULL;
|
||||||
return ECORE_CALLBACK_CANCEL;
|
return ECORE_CALLBACK_CANCEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
Eldbus_Connection *conn;
|
|
||||||
Eldbus_Object *obj;
|
Eldbus_Object *obj;
|
||||||
Eldbus_Proxy *proxy;
|
Eldbus_Proxy *proxy;
|
||||||
|
|
||||||
|
@ -317,11 +326,14 @@ main(void)
|
||||||
|
|
||||||
eldbus_name_owner_changed_callback_add(conn, BUS, on_name_owner_changed,
|
eldbus_name_owner_changed_callback_add(conn, BUS, on_name_owner_changed,
|
||||||
conn, EINA_TRUE);
|
conn, EINA_TRUE);
|
||||||
ecore_timer_add(30, finish, NULL);
|
timeout = ecore_timer_add(30, finish, NULL);
|
||||||
|
|
||||||
ecore_main_loop_begin();
|
ecore_main_loop_begin();
|
||||||
|
|
||||||
eldbus_connection_unref(conn);
|
if (timeout)
|
||||||
|
ecore_timer_del(timeout);
|
||||||
|
if (conn)
|
||||||
|
eldbus_connection_unref(conn);
|
||||||
|
|
||||||
eldbus_shutdown();
|
eldbus_shutdown();
|
||||||
ecore_shutdown();
|
ecore_shutdown();
|
||||||
|
|
|
@ -756,26 +756,22 @@ static Eina_Bool
|
||||||
eldbus_idler(void *data)
|
eldbus_idler(void *data)
|
||||||
{
|
{
|
||||||
Eldbus_Connection *conn = data;
|
Eldbus_Connection *conn = data;
|
||||||
DBusConnection *dbus_conn;
|
|
||||||
|
|
||||||
DBG("Connection@%p: Dispatch status: %d", 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 ==
|
if (dbus_connection_get_dispatch_status(conn->dbus_conn) ==
|
||||||
dbus_connection_get_dispatch_status(conn->dbus_conn))
|
DBUS_DISPATCH_COMPLETE)
|
||||||
{
|
{
|
||||||
DBG("Connection@%p: Dispatch complete, idler@%p finishing",
|
DBG("Connection@%p: Dispatch complete, idler@%p finishing",
|
||||||
conn, conn->idler);
|
conn, conn->idler);
|
||||||
conn->idler = NULL;
|
conn->idler = NULL;
|
||||||
return ECORE_CALLBACK_CANCEL;
|
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);
|
DBG("Connection@%p: Dispatching", conn);
|
||||||
dbus_connection_dispatch(dbus_conn);
|
eldbus_connection_ref(conn);
|
||||||
dbus_connection_unref(dbus_conn);
|
dbus_connection_dispatch(conn->dbus_conn);
|
||||||
|
eldbus_connection_unref(conn);
|
||||||
return ECORE_CALLBACK_RENEW;
|
return ECORE_CALLBACK_RENEW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -784,18 +780,24 @@ cb_dispatch_status(DBusConnection *dbus_conn EINA_UNUSED, DBusDispatchStatus new
|
||||||
{
|
{
|
||||||
Eldbus_Connection *conn = data;
|
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);
|
DBG("Connection@%p: Dispatch status: %d", conn, new_status);
|
||||||
|
|
||||||
if ((new_status == DBUS_DISPATCH_DATA_REMAINS) && (!conn->idler))
|
if ((new_status == DBUS_DISPATCH_DATA_REMAINS) && (!conn->idler))
|
||||||
{
|
{
|
||||||
conn->idler = ecore_idler_add(eldbus_idler, conn);
|
conn->idler = ecore_idler_add(eldbus_idler, conn);
|
||||||
DBG("Connection@%p: Adding idler@%p to handle remaining dispatch data",
|
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))
|
else if ((new_status != DBUS_DISPATCH_DATA_REMAINS) && (conn->idler))
|
||||||
{
|
{
|
||||||
DBG("Connection@%p: No remaining dispatch data, clearing idler@%p",
|
DBG("Connection@%p: No remaining dispatch data, clearing idler@%p",
|
||||||
conn, conn->idler);
|
conn, conn->idler);
|
||||||
|
|
||||||
ecore_idler_del(conn->idler);
|
ecore_idler_del(conn->idler);
|
||||||
conn->idler = NULL;
|
conn->idler = NULL;
|
||||||
|
@ -1010,14 +1012,14 @@ _connection_get(Eldbus_Connection_Type type, const char *address)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
eldbus_connection_setup(conn);
|
|
||||||
conn->type = type;
|
conn->type = type;
|
||||||
conn->refcount = 1;
|
conn->refcount = 1;
|
||||||
EINA_MAGIC_SET(conn, ELDBUS_CONNECTION_MAGIC);
|
EINA_MAGIC_SET(conn, ELDBUS_CONNECTION_MAGIC);
|
||||||
conn->names = eina_hash_string_superfast_new(NULL);
|
conn->names = eina_hash_string_superfast_new(NULL);
|
||||||
|
eldbus_connection_setup(conn);
|
||||||
|
|
||||||
eldbus_signal_handler_add(conn, NULL, DBUS_PATH_LOCAL, DBUS_INTERFACE_LOCAL,
|
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);
|
obj = eldbus_object_get(conn, ELDBUS_FDO_BUS, ELDBUS_FDO_PATH);
|
||||||
conn->fdo_proxy = eldbus_proxy_get(obj, ELDBUS_FDO_INTERFACE);
|
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);
|
EINA_MAGIC_SET(conn, EINA_MAGIC_NONE);
|
||||||
|
//will trigger a cb_dispatch_status()
|
||||||
dbus_connection_close(conn->dbus_conn);
|
dbus_connection_close(conn->dbus_conn);
|
||||||
dbus_connection_unref(conn->dbus_conn);
|
dbus_connection_unref(conn->dbus_conn);
|
||||||
conn->dbus_conn = NULL;
|
conn->dbus_conn = NULL;
|
||||||
|
|
Loading…
Reference in New Issue