raster pushed a commit to branch master.

commit 072c140201a3000aadd279f33f7529a0da332337
Author: Carsten Haitzler (Rasterman) <[email protected]>
Date:   Mon Aug 26 12:08:15 2013 +0900

    try and fix up valgrind+segv issues with ethumb and freed data access
---
 src/lib/ethumb_client/ethumb_client.c | 125 +++++++++++++++++++++++++---------
 1 file changed, 91 insertions(+), 34 deletions(-)

diff --git a/src/lib/ethumb_client/ethumb_client.c 
b/src/lib/ethumb_client/ethumb_client.c
index e306dfb..b21ddf4 100644
--- a/src/lib/ethumb_client/ethumb_client.c
+++ b/src/lib/ethumb_client/ethumb_client.c
@@ -117,9 +117,11 @@ struct _Ethumb_Client
       Eina_Free_Cb         free_data;
    } die;
    Eldbus_Proxy           *proxy;
+   Eldbus_Signal_Handler  *generated_sig_handler;
    EINA_REFCOUNT;
    Eina_Bool              connected : 1;
    Eina_Bool              server_started : 1;
+   Eina_Bool              invalid : 1;
 };
 
 struct _ethumb_pending_add
@@ -132,7 +134,7 @@ struct _ethumb_pending_add
    Ethumb_Client_Generate_Cb generated_cb;
    void                     *data;
    Eina_Free_Cb              free_data;
-   Eldbus_Pending            *pending_call;
+   Eldbus_Pending           *pending_call;
    Ethumb_Client            *client;
 };
 
@@ -142,6 +144,7 @@ struct _ethumb_pending_remove
    Ethumb_Client_Generate_Cancel_Cb cancel_cb;
    void                            *data;
    Eina_Free_Cb                     free_data;
+   Eldbus_Pending                  *pending_call;
    Ethumb_Client                   *client;
 };
 
@@ -197,13 +200,16 @@ _ethumb_client_free(Ethumb_Client *client)
    void *data;
    Eldbus_Object *obj;
 
-   if (!client->connected)
-     goto end_connection;
-
+   if (client->invalid) return;
+   client->invalid = EINA_TRUE;
    EINA_LIST_FREE(client->pending_add, data)
      {
         struct _ethumb_pending_add *pending = data;
-        eldbus_pending_cancel(pending->pending_call);
+        pending->client = NULL;
+        if (pending->pending_call)
+          eldbus_pending_cancel(pending->pending_call);
+        else
+          free(pending);
      }
 
    EINA_LIST_FREE(client->pending_gen, data)
@@ -223,22 +229,47 @@ _ethumb_client_free(Ethumb_Client *client)
         struct _ethumb_pending_remove *pending = data;
         if (pending->free_data)
           pending->free_data(pending->data);
-        free(pending);
+        pending->client = NULL;
+        if (pending->pending_call)
+          eldbus_pending_cancel(pending->pending_call);
+        else
+          free(pending);
      }
 
-end_connection:
    if (client->old_ethumb_conf)
-     ethumb_free(client->old_ethumb_conf);
+     {
+        ethumb_free(client->old_ethumb_conf);
+        client->old_ethumb_conf = NULL;
+     }
 
-   ethumb_free(client->ethumb);
+   if (client->ethumb)
+     {
+        ethumb_free(client->ethumb);
+        client->ethumb = NULL;
+     }
 
-   eldbus_name_owner_changed_callback_del(client->conn, _ethumb_dbus_bus_name,
-                                         _ethumb_client_name_owner_changed,
-                                         client);
-   obj = eldbus_proxy_object_get(client->proxy);
-   eldbus_proxy_unref(client->proxy);
-   eldbus_object_unref(obj);
-   if (client->conn) eldbus_connection_unref(client->conn);
+   if (client->conn)
+     eldbus_name_owner_changed_callback_del(client->conn,
+                                            _ethumb_dbus_bus_name,
+                                            _ethumb_client_name_owner_changed,
+                                            client);
+   if (client->generated_sig_handler)
+     {
+        eldbus_signal_handler_del(client->generated_sig_handler);
+        client->generated_sig_handler = NULL;
+     }
+   if (client->proxy)
+     {
+        obj = eldbus_proxy_object_get(client->proxy);
+        eldbus_proxy_unref(client->proxy);
+        client->proxy = NULL;
+        if (obj) eldbus_object_unref(obj);
+     }
+   if (client->conn)
+     {
+        eldbus_connection_unref(client->conn);
+        client->conn = NULL;
+     }
 
    if (client->connect.free_data)
      client->connect.free_data(client->connect.data);
@@ -266,6 +297,7 @@ static void
 _ethumb_client_name_owner_changed(void *context, const char *bus EINA_UNUSED, 
const char *old_id, const char *new_id)
 {
    Ethumb_Client *client = context;
+
    DBG("NameOwnerChanged from=[%s] to=[%s]", old_id, new_id);
    if (new_id[0])
      {
@@ -278,6 +310,7 @@ _ethumb_client_name_owner_changed(void *context, const char 
*bus EINA_UNUSED, co
         return;
      }
    INF("Server disconnected");
+   EINA_REFCOUNT_REF(client);
    client->connected = EINA_FALSE;
    if (client->die.cb)
      {
@@ -290,6 +323,7 @@ _ethumb_client_name_owner_changed(void *context, const char 
*bus EINA_UNUSED, co
         client->die.free_data = NULL;
         client->die.data = NULL;
      }
+   EINA_REFCOUNT_UNREF(client) _ethumb_client_free(client);
 }
 
 static void
@@ -297,10 +331,11 @@ _ethumb_client_report_connect(Ethumb_Client *client, 
Eina_Bool success)
 {
    if (!client->connect.cb)
      {
-        ERR("already called?!");
+        //ERR("already called?!");
         return;
      }
 
+   EINA_REFCOUNT_REF(client);
    if (success)
      INF("Success connecting to Ethumb server.");
    else
@@ -314,6 +349,7 @@ _ethumb_client_report_connect(Ethumb_Client *client, 
Eina_Bool success)
      }
    client->connect.cb = NULL;
    client->connect.data = NULL;
+   EINA_REFCOUNT_UNREF(client) _ethumb_client_free(client);
 }
 
 static void
@@ -338,10 +374,19 @@ _ethumb_client_new_cb(void *data, const Eldbus_Message 
*msg, Eldbus_Pending *pen
         return;
      }
 
-   obj = eldbus_object_get(client->conn, _ethumb_dbus_bus_name, opath);
-   client->proxy = eldbus_proxy_get(obj, _ethumb_dbus_objects_interface);
-   eldbus_proxy_signal_handler_add(client->proxy, "generated",
-                                  _ethumb_client_generated_cb, client);
+   if (client->generated_sig_handler)
+     {
+        eldbus_signal_handler_del(client->generated_sig_handler);
+        client->generated_sig_handler = NULL;
+     }
+   if (!client->proxy)
+     {
+        obj = eldbus_object_get(client->conn, _ethumb_dbus_bus_name, opath);
+        client->proxy = eldbus_proxy_get(obj, _ethumb_dbus_objects_interface);
+     }
+   client->generated_sig_handler =
+     eldbus_proxy_signal_handler_add(client->proxy, "generated",
+                                     _ethumb_client_generated_cb, client);
    _ethumb_client_report_connect(client, 1);
 }
 
@@ -382,8 +427,7 @@ _ethumb_client_exists_end(void *data, Ecore_Thread *thread 
EINA_UNUSED)
                       ethumb_exists(cb->client->ethumb));
 
         cb->client->ethumb = tmp;
-        EINA_REFCOUNT_UNREF(cb->client)
-        _ethumb_client_free(cb->client);
+        EINA_REFCOUNT_UNREF(cb->client) _ethumb_client_free(cb->client);
         ethumb_free(cb->dup);
         free(cb);
      }
@@ -580,8 +624,7 @@ ethumb_client_disconnect(Ethumb_Client *client)
 {
    EINA_SAFETY_ON_NULL_RETURN(client);
 
-   EINA_REFCOUNT_UNREF(client)
-   _ethumb_client_free(client);
+   EINA_REFCOUNT_UNREF(client) _ethumb_client_free(client);
 }
 
 /**
@@ -838,6 +881,7 @@ _ethumb_client_generated_cb(void *data, const 
Eldbus_Message *msg)
    struct _ethumb_pending_gen *pending;
    Eina_List *l;
 
+   if (!client) return;
    if (!eldbus_message_arguments_get(msg, "iayayb", &id, &thumb_iter,
                                     &thumb_key_iter, &success))
      {
@@ -890,6 +934,8 @@ _ethumb_client_queue_add_cb(void *data, const 
Eldbus_Message *msg, Eldbus_Pendin
    struct _ethumb_pending_gen *generating;
    Ethumb_Client *client = pending->client;
 
+   pending->pending_call = NULL;
+   if (!client) goto end;
    client->pending_add = eina_list_remove(client->pending_add, pending);
 
    if (eldbus_message_error_get(msg, &errname, &errmsg))
@@ -957,8 +1003,8 @@ _ethumb_client_queue_add(Ethumb_Client *client, const char 
*file, const char *ke
    _ethumb_client_dbus_append_bytearray(main_itr, thumb_key);
 
    pending->pending_call = eldbus_proxy_send(client->proxy, msg,
-                                            _ethumb_client_queue_add_cb,
-                                            pending, -1);
+                                             _ethumb_client_queue_add_cb,
+                                             pending, -1);
    client->pending_add = eina_list_append(client->pending_add, pending);
 
    return pending->id;
@@ -972,6 +1018,8 @@ _ethumb_client_queue_remove_cb(void *data, const 
Eldbus_Message *msg, Eldbus_Pen
    Ethumb_Client *client = pending->client;
    const char *errname, *errmsg;
 
+   pending->pending_call = NULL;
+   if (!client) goto end;
    client->pending_remove = eina_list_remove(client->pending_remove, pending);
 
    if (eldbus_message_error_get(msg, &errname, &errmsg))
@@ -1030,8 +1078,10 @@ ethumb_client_generate_cancel(Ethumb_Client *client, int 
id, Ethumb_Client_Gener
    pending->free_data = free_data;
    pending->client = client;
 
-   eldbus_proxy_call(client->proxy, "queue_remove",
-                    _ethumb_client_queue_remove_cb, pending, -1, "i", 
pending->id);
+   pending->pending_call =
+     eldbus_proxy_call(client->proxy, "queue_remove",
+                       _ethumb_client_queue_remove_cb, pending, -1,
+                       "i", pending->id);
    client->pending_remove = eina_list_append(client->pending_remove, pending);
 
    /*
@@ -1050,6 +1100,7 @@ ethumb_client_generate_cancel(Ethumb_Client *client, int 
id, Ethumb_Client_Gener
              continue;
           }
         eldbus_pending_cancel(pending_add->pending_call);
+        pending_add->pending_call = NULL;
         found = 1;
         break;
      }
@@ -1096,7 +1147,11 @@ ethumb_client_generate_cancel_all(Ethumb_Client *client)
    EINA_LIST_FREE(client->pending_add, data)
      {
         struct _ethumb_pending_add *pending = data;
-        eldbus_pending_cancel(pending->pending_call);
+        if (pending->pending_call)
+          eldbus_pending_cancel(pending->pending_call);
+        pending->pending_call = NULL;
+        pending->client = NULL;
+        free(pending);
      }
 
    EINA_LIST_FREE(client->pending_gen, data)
@@ -1938,8 +1993,7 @@ ethumb_client_thumb_exists_cancel(Ethumb_Exists *exists)
      ecore_thread_cancel(async->thread);
 
    ethumb_free(exists->dup);
-   EINA_REFCOUNT_UNREF(exists->client)
-   _ethumb_client_free(exists->client);
+   EINA_REFCOUNT_UNREF(exists->client) _ethumb_client_free(exists->client);
    free(exists);
 }
 
@@ -2044,10 +2098,13 @@ static Eina_List *idle_tasks[2] = { NULL, NULL };
 static void
 _ethumb_client_async_free(Ethumb_Client_Async *async)
 {
-   EINA_REFCOUNT_UNREF(async->client)
-   _ethumb_client_free(async->client);
+   Ethumb_Client *client = async->client;
    ethumb_free(async->dup);
    free(async);
+   if (client)
+     {
+        EINA_REFCOUNT_UNREF(client) _ethumb_client_free(client);
+     }
 }
 
 static void

-- 

------------------------------------------------------------------------------
Introducing Performance Central, a new site from SourceForge and 
AppDynamics. Performance Central is your source for news, insights, 
analysis and resources for efficient Application Performance Management. 
Visit us today!
http://pubads.g.doubleclick.net/gampad/clk?id=48897511&iu=/4140/ostg.clktrk

Reply via email to