zehortigoza pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=63abe9b00cc02940361372cb0881d3f7fbb682f2

commit 63abe9b00cc02940361372cb0881d3f7fbb682f2
Author: José Roberto de Souza <jose.so...@intel.com>
Date:   Wed Dec 17 16:57:03 2014 -0200

    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
---
 src/lib/eldbus/eldbus_core.c    |  2 ++
 src/lib/eldbus/eldbus_object.c  | 21 +++++++++++++++------
 src/lib/eldbus/eldbus_pending.c | 22 ++++++++++++++++------
 src/lib/eldbus/eldbus_proxy.c   | 20 ++++++++++++++------
 4 files changed, 47 insertions(+), 18 deletions(-)

diff --git a/src/lib/eldbus/eldbus_core.c b/src/lib/eldbus/eldbus_core.c
index 71ee4e4..48ea7c0 100644
--- a/src/lib/eldbus/eldbus_core.c
+++ b/src/lib/eldbus/eldbus_core.c
@@ -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;
 }
 
diff --git a/src/lib/eldbus/eldbus_object.c b/src/lib/eldbus/eldbus_object.c
index 64047e6..a859ba1 100644
--- a/src/lib/eldbus/eldbus_object.c
+++ b/src/lib/eldbus/eldbus_object.c
@@ -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;
diff --git a/src/lib/eldbus/eldbus_pending.c b/src/lib/eldbus/eldbus_pending.c
index efa3970..bd897b9 100644
--- a/src/lib/eldbus/eldbus_pending.c
+++ b/src/lib/eldbus/eldbus_pending.c
@@ -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;
 }
 
diff --git a/src/lib/eldbus/eldbus_proxy.c b/src/lib/eldbus/eldbus_proxy.c
index 0d2ba15..4d76a56 100644
--- a/src/lib/eldbus/eldbus_proxy.c
+++ b/src/lib/eldbus/eldbus_proxy.c
@@ -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));
 

-- 


Reply via email to