Fix wrong resource management 92/171792/2
authorjusung son <jusung07.son@samsung.com>
Wed, 7 Mar 2018 09:19:26 +0000 (18:19 +0900)
committerjusung son <jusung07.son@samsung.com>
Wed, 7 Mar 2018 10:38:22 +0000 (19:38 +0900)
 - callback information protection logic
 - socket leak

Change-Id: If11518db21aefddf8de30dc2463338ccf5d86109
Signed-off-by: jusung son <jusung07.son@samsung.com>
vconf-compat/vconf.c

index ef1adcb..adc7db6 100755 (executable)
@@ -58,7 +58,8 @@ struct noti {
 struct noti_cb {
        vconf_callback_fn cb;
        void *user_data;
-       int ref_cnt;
+       bool active;
+       bool in_cb;
 };
 
 static bool last_result;
@@ -174,8 +175,9 @@ static void free_noti(struct noti *noti)
        for (l = noti->noti_list, n = g_list_next(l);
                        l; l = n, n = g_list_next(n)) {
                struct noti_cb *noticb = l->data;
-               noticb->ref_cnt--;
-               if (noticb->ref_cnt == 0) {
+               noticb->active = false;
+
+               if (!noticb->in_cb) {
                        noti->noti_list = g_list_delete_link(noti->noti_list, l);
                        free(noticb);
                }
@@ -334,7 +336,7 @@ static GList *copy_noti_list(GList *noti_list)
        pthread_mutex_lock(&vconf_lock);
        for (l = noti_list; l; l = g_list_next(l)) {
                struct noti_cb *noticb = l->data;
-               noticb->ref_cnt++;
+               noticb->in_cb = true;
        }
        copy = g_list_copy(noti_list);
        pthread_mutex_unlock(&vconf_lock);
@@ -353,9 +355,9 @@ static GList *free_copy_list(GList *noti_list, GList *copy_list)
        for (l = noti_list, ll = g_list_next(l); l;
                        l = ll, ll = g_list_next(ll)) {
                struct noti_cb *noticb = l->data;
+               noticb->in_cb = false;
 
-               noticb->ref_cnt--;
-               if (noticb->ref_cnt == 0) {
+               if (!noticb->active) {
                        noti_list = g_list_delete_link(noti_list, l);
                        free(noticb);
                }
@@ -438,8 +440,13 @@ static int add_noti(struct noti *noti, vconf_callback_fn cb, void *user_data)
 
        noticb = find_noti_cb(noti, cb);
        if (noticb) {
-               errno = EEXIST;
-               return -1;
+               if (noticb->active) {
+                       errno = EEXIST;
+                       return -1;
+               } else {
+                       noticb->active = true;
+                       return 0;
+               }
        }
 
        noticb = calloc(1, sizeof(*noticb));
@@ -448,7 +455,8 @@ static int add_noti(struct noti *noti, vconf_callback_fn cb, void *user_data)
 
        noticb->cb = cb;
        noticb->user_data = user_data;
-       noticb->ref_cnt = 1;
+       noticb->active = true;
+       noticb->in_cb = false;
 
        noti->noti_list = g_list_append(noti->noti_list, noticb);
 
@@ -596,20 +604,22 @@ EXPORT int vconf_ignore_key_changed(const char *key, vconf_callback_fn cb)
 
        noti = g_hash_table_lookup(noti_tbl, key);
        if (!noti) {
+               _close();
                pthread_mutex_unlock(&vconf_lock);
                errno = ENOENT;
                return -1;
        }
 
        noticb = find_noti_cb(noti, cb);
-       if (!noticb) {
+       if (!noticb || !noticb->active) {
+               _close();
                pthread_mutex_unlock(&vconf_lock);
                errno = ENOENT;
                return -1;
        }
 
-       noticb->ref_cnt--;
-       if (noticb->ref_cnt == 0) {
+       noticb->active = false;
+       if (!noticb->in_cb) {
                noti->noti_list = g_list_remove(noti->noti_list, noticb);
                free(noticb);
        }
@@ -617,6 +627,7 @@ EXPORT int vconf_ignore_key_changed(const char *key, vconf_callback_fn cb)
        cnt = unregister_noti(noti);
 
        if (cnt > 0) {
+               _close();
                pthread_mutex_unlock(&vconf_lock);
                return 0;
        }