forked from enlightenment/efl
eldbus: Fix crash when removing the last reference of the message container inside of the message callback
If user try to remove the last reference of proxy, object, connection or eldbus(lib) inside of message callback it was causing the eldbus_pending_dispatch() being called 2 times, one because of the eldbus_cancel() that is triggered when the last reference of the message parent is removed and another after the return of the user callback. ==6545== Invalid read of size 8 ==6545== at 0x52F784E: eldbus_cbs_free_dispatch (eldbus_core.c:266) ==6545== by 0x53064AA: eldbus_pending_dispatch (eldbus_pending.c:227) ==6545== by 0x5305961: cb_pending (eldbus_pending.c:74) ==6545== by 0x6B29DB1: ??? (in /usr/lib/libdbus-1.so.3.8.9) ==6545== by 0x6B2D280: dbus_connection_dispatch (in /usr/lib/libdbus-1.so.3.8.9) ==6545== by 0x52F93B4: eldbus_idler (eldbus_core.c:773) ==6545== by 0x4E4B300: _ecore_call_task_cb (ecore_private.h:305) ==6545== by 0x4E4B78F: _ecore_idler_all_call (ecore_idler.c:143) ==6545== by 0x4E4EA73: _ecore_main_loop_spin_core (ecore_main.c:1768) ==6545== by 0x4E4EAF1: _ecore_main_loop_spin_timers (ecore_main.c:1802) ==6545== by 0x4E4ED01: _ecore_main_loop_iterate_internal (ecore_main.c:1925) ==6545== by 0x4E4D03B: ecore_main_loop_begin (ecore_main.c:983) ==6545== Address 0x701aa78 is 104 bytes inside a block of size 128 free'd ==6545== at 0x4C2B200: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==6545== by 0x530655B: eldbus_pending_dispatch (eldbus_pending.c:241) ==6545== by 0x5306763: eldbus_pending_cancel (eldbus_pending.c:259) ==6545== by 0x52F29DB: _eldbus_proxy_clear (eldbus_proxy.c:146) ==6545== by 0x52F3057: _eldbus_proxy_unref (eldbus_proxy.c:244) ==6545== by 0x52F3393: eldbus_proxy_unref (eldbus_proxy.c:264) ==6545== by 0x401039: on_get_playlists (banshee.c:53) ==6545== by 0x5306493: eldbus_pending_dispatch (eldbus_pending.c:225) ==6545== by 0x5305961: cb_pending (eldbus_pending.c:74) ==6545== by 0x6B29DB1: ??? (in /usr/lib/libdbus-1.so.3.8.9) ==6545== by 0x6B2D280: dbus_connection_dispatch (in /usr/lib/libdbus-1.so.3.8.9) ==6545== by 0x52F93B4: eldbus_idler (eldbus_core.c:773) Now we will remove the pending from parent pending list before call the user callback, this way only the pending messages will be canceled. Also we need increase the eldbus reference before call dbus_connection_dispatch() or user could remove the last reference of eldbus inside of a message callback when we still are holding one reference of the connection. @fix ref T1908
This commit is contained in:
parent
78d5bb17d7
commit
63abe9b00c
|
@ -769,9 +769,11 @@ eldbus_idler(void *data)
|
|||
return ECORE_CALLBACK_CANCEL;
|
||||
}
|
||||
DBG("Connection@%p: Dispatching", conn);
|
||||
eldbus_init();
|
||||
eldbus_connection_ref(conn);
|
||||
dbus_connection_dispatch(conn->dbus_conn);
|
||||
eldbus_connection_unref(conn);
|
||||
eldbus_shutdown();
|
||||
return ECORE_CALLBACK_RENEW;
|
||||
}
|
||||
|
||||
|
|
|
@ -560,12 +560,15 @@ eldbus_object_path_get(const Eldbus_Object *obj)
|
|||
}
|
||||
|
||||
static void
|
||||
_on_pending_free(void *data, const void *dead_pointer)
|
||||
_on_object_message_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
|
||||
{
|
||||
Eldbus_Object *obj = data;
|
||||
Eldbus_Pending *pending = (Eldbus_Pending*) dead_pointer;
|
||||
Eldbus_Message_Cb cb = eldbus_pending_data_del(pending, "__user_cb");
|
||||
Eldbus_Object *obj = eldbus_pending_data_del(pending, "__object");
|
||||
|
||||
ELDBUS_OBJECT_CHECK(obj);
|
||||
obj->pendings = eina_inlist_remove(obj->pendings, EINA_INLIST_GET(pending));
|
||||
|
||||
cb(data, msg, pending);
|
||||
}
|
||||
|
||||
EAPI Eldbus_Pending *
|
||||
|
@ -576,11 +579,17 @@ eldbus_object_send(Eldbus_Object *obj, Eldbus_Message *msg, Eldbus_Message_Cb cb
|
|||
ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(msg, NULL);
|
||||
|
||||
pending = _eldbus_connection_send(obj->conn, msg, cb, cb_data, timeout);
|
||||
if (!cb) return NULL;
|
||||
if (!cb)
|
||||
{
|
||||
_eldbus_connection_send(obj->conn, msg, NULL, NULL, timeout);
|
||||
return NULL;
|
||||
}
|
||||
pending = _eldbus_connection_send(obj->conn, msg, _on_object_message_cb,
|
||||
cb_data, timeout);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(pending, NULL);
|
||||
|
||||
eldbus_pending_free_cb_add(pending, _on_pending_free, obj);
|
||||
eldbus_pending_data_set(pending, "__user_cb", cb);
|
||||
eldbus_pending_data_set(pending, "__object", obj);
|
||||
obj->pendings = eina_inlist_append(obj->pendings, EINA_INLIST_GET(pending));
|
||||
|
||||
return pending;
|
||||
|
|
|
@ -80,10 +80,14 @@ cleanup:
|
|||
}
|
||||
|
||||
static void
|
||||
_on_pending_free(void *data, const void *dead_pointer)
|
||||
_on_conn_message_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
|
||||
{
|
||||
Eldbus_Connection *conn = data;
|
||||
eldbus_connection_pending_del(conn, (void *)dead_pointer);
|
||||
Eldbus_Message_Cb cb = eldbus_pending_data_del(pending, "__user_cb");
|
||||
Eldbus_Connection *conn = eldbus_pending_data_del(pending, "__connection");
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(conn);
|
||||
eldbus_connection_pending_del(conn, pending);
|
||||
cb(data, msg, pending);
|
||||
}
|
||||
|
||||
EAPI Eldbus_Pending *
|
||||
|
@ -94,12 +98,18 @@ eldbus_connection_send(Eldbus_Connection *conn, Eldbus_Message *msg, Eldbus_Mess
|
|||
EINA_SAFETY_ON_NULL_RETURN_VAL(conn, NULL);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(msg, NULL);
|
||||
|
||||
pending = _eldbus_connection_send(conn, msg, cb, cb_data, timeout);
|
||||
if (!cb) return NULL;
|
||||
if (!cb)
|
||||
{
|
||||
_eldbus_connection_send(conn, msg, NULL, NULL, timeout);
|
||||
return NULL;
|
||||
}
|
||||
pending = _eldbus_connection_send(conn, msg, _on_conn_message_cb, cb_data,
|
||||
timeout);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(pending, NULL);
|
||||
|
||||
eldbus_pending_data_set(pending, "__user_cb", cb);
|
||||
eldbus_pending_data_set(pending, "__connection", conn);
|
||||
eldbus_connection_pending_add(conn, pending);
|
||||
eldbus_pending_free_cb_add(pending, _on_pending_free, conn);
|
||||
return pending;
|
||||
}
|
||||
|
||||
|
|
|
@ -521,13 +521,15 @@ eldbus_proxy_interface_get(const Eldbus_Proxy *proxy)
|
|||
}
|
||||
|
||||
static void
|
||||
_on_pending_free(void *data, const void *dead_pointer)
|
||||
_on_proxy_message_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
|
||||
{
|
||||
Eldbus_Proxy *proxy = data;
|
||||
Eldbus_Pending *pending = (Eldbus_Pending *)dead_pointer;
|
||||
Eldbus_Message_Cb cb = eldbus_pending_data_del(pending, "__user_cb");
|
||||
Eldbus_Proxy *proxy = eldbus_pending_data_del(pending, "__proxy");
|
||||
|
||||
ELDBUS_PROXY_CHECK(proxy);
|
||||
proxy->pendings = eina_inlist_remove(proxy->pendings,
|
||||
EINA_INLIST_GET(pending));
|
||||
cb(data, msg, pending);
|
||||
}
|
||||
|
||||
static Eldbus_Pending *
|
||||
|
@ -535,11 +537,17 @@ _eldbus_proxy_send(Eldbus_Proxy *proxy, Eldbus_Message *msg, Eldbus_Message_Cb c
|
|||
{
|
||||
Eldbus_Pending *pending;
|
||||
|
||||
pending = _eldbus_connection_send(proxy->obj->conn, msg, cb, cb_data, timeout);
|
||||
if (!cb) return NULL;
|
||||
if (!cb)
|
||||
{
|
||||
_eldbus_connection_send(proxy->obj->conn, msg, NULL, NULL, timeout);
|
||||
return NULL;
|
||||
}
|
||||
pending = _eldbus_connection_send(proxy->obj->conn, msg,
|
||||
_on_proxy_message_cb, cb_data, timeout);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(pending, NULL);
|
||||
|
||||
eldbus_pending_free_cb_add(pending, _on_pending_free, proxy);
|
||||
eldbus_pending_data_set(pending, "__user_cb", cb);
|
||||
eldbus_pending_data_set(pending, "__proxy", proxy);
|
||||
proxy->pendings = eina_inlist_append(proxy->pendings,
|
||||
EINA_INLIST_GET(pending));
|
||||
|
||||
|
|
Loading…
Reference in New Issue