Use recursive mutex 63/271963/2
authorHwankyu Jhun <h.jhun@samsung.com>
Fri, 4 Mar 2022 01:48:26 +0000 (10:48 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Fri, 4 Mar 2022 01:58:09 +0000 (10:58 +0900)
To avoid deadlock state, vconf API uses recursive mutex.

Change-Id: I30bf03f40d2c8f06cd5499926bc988015bec20fe
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
vconf-compat/vconf.c

index f81a762..2f7ca9c 100644 (file)
@@ -52,11 +52,14 @@ static int last_errno;
                last_result = false; \
        } while (0)
 
+#define VCONF_CTOR __attribute__((constructor))
+#define VCONF_DTOR __attribute__((destructor))
+
 static void _vconf_restore_noti_cb(gpointer key, gpointer value, gpointer user_data);
 static void _vconf_con_close(void);
 static gboolean _vconf_call_noti_cb(gpointer data);
 
-static pthread_mutex_t vconf_lock = PTHREAD_MUTEX_INITIALIZER;
+static GRecMutex vconf_mutex;
 static int _refcnt;
 static struct buxton_client *client;
 static struct buxton_layer *system_layer;
@@ -87,6 +90,16 @@ struct callback_info {
 static struct noti_cb *_vconf_find_noti_cb(struct noti *noti, vconf_callback_fn cb);
 static void _vconf_to_vconf_t(const struct buxton_value *val, keynode_t *node);
 
+static void _vconf_mutex_lock(void)
+{
+       g_rec_mutex_lock(&vconf_mutex);
+}
+
+static void _vconf_mutex_unlock(void)
+{
+       g_rec_mutex_unlock(&vconf_mutex);
+}
+
 static GSource *_vconf_idle_add_full(GMainContext *context, guint priority, GSourceFunc func,
                gpointer data)
 {
@@ -210,8 +223,12 @@ static struct callback_info *_vconf_create_callback_info(const char *key,
        return cb_info;
 }
 
-__attribute__((destructor))
-static void _vconf_finish(void)
+VCONF_CTOR static void _vconf_init(void)
+{
+       g_rec_mutex_init(&vconf_mutex);
+}
+
+VCONF_DTOR static void _vconf_finish(void)
 {
        /* force close */
        if (_refcnt > 0) {
@@ -221,6 +238,11 @@ static void _vconf_finish(void)
 
        if (gsource_tbl)
                g_hash_table_remove_all(gsource_tbl);
+
+       if (g_rec_mutex_trylock(&vconf_mutex))
+               g_rec_mutex_unlock(&vconf_mutex);
+
+       g_rec_mutex_clear(&vconf_mutex);
 }
 
 EXPORT char *vconf_keynode_get_name(keynode_t *keynode)
@@ -383,10 +405,10 @@ static void _vconf_restore_connection(enum buxton_status status,
                return;
 
        /* LCOV_EXCL_START */
-       pthread_mutex_lock(&vconf_lock);
+       _vconf_mutex_lock();
        if (!noti_tbl) {
                _refcnt = 0;
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                return;
        }
 
@@ -395,12 +417,12 @@ static void _vconf_restore_connection(enum buxton_status status,
        if (r != 0) {
                _refcnt = 0;
                LOGE("Can't connect to buxton: %d", buxton_err_get_errno());
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                return;
        }
 
        g_hash_table_foreach(noti_tbl, (GHFunc)_vconf_restore_noti_cb, NULL);
-       pthread_mutex_unlock(&vconf_lock);
+       _vconf_mutex_unlock();
        /* LCOV_EXCL_STOP */
 }
 
@@ -502,26 +524,26 @@ static gboolean _vconf_call_noti_cb(gpointer data)
 
        cb_info->source = NULL;
 
-       pthread_mutex_lock(&vconf_lock);
+       _vconf_mutex_lock();
        noti = g_hash_table_lookup(noti_tbl, node->keyname);
        if (!noti) {
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                g_hash_table_remove(gsource_tbl, GINT_TO_POINTER(cb_info->id));
                return G_SOURCE_REMOVE;
        }
 
        if (!_vconf_find_noti_cb(noti, noticb->cb)) {
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                g_hash_table_remove(gsource_tbl, GINT_TO_POINTER(cb_info->id));
                return G_SOURCE_REMOVE;
        }
-       pthread_mutex_unlock(&vconf_lock);
+       _vconf_mutex_unlock();
 
        noticb->cb(node, noticb->user_data);
 
-       pthread_mutex_lock(&vconf_lock);
+       _vconf_mutex_lock();
        g_hash_table_remove(gsource_tbl, GINT_TO_POINTER(cb_info->id));
-       pthread_mutex_unlock(&vconf_lock);
+       _vconf_mutex_unlock();
 
        return G_SOURCE_REMOVE;
 }
@@ -534,10 +556,10 @@ static void _vconf_notify_cb(const struct buxton_layer *layer, const char *key,
        struct noti* noti;
        GList *iter;
 
-       pthread_mutex_lock(&vconf_lock);
+       _vconf_mutex_lock();
        noti = g_hash_table_lookup(noti_tbl, key);
        if (!noti) {
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                return;
        }
 
@@ -551,14 +573,14 @@ static void _vconf_notify_cb(const struct buxton_layer *layer, const char *key,
                noticb = iter->data;
                cb_info = _vconf_create_callback_info(key, val, noticb);
                if (!cb_info) {
-                       pthread_mutex_unlock(&vconf_lock);
+                       _vconf_mutex_unlock();
                        return;
                }
 
                g_hash_table_insert(gsource_tbl, GINT_TO_POINTER(cb_info->id),
                                cb_info);
        }
-       pthread_mutex_unlock(&vconf_lock);
+       _vconf_mutex_unlock();
 }
 
 static struct noti_cb *_vconf_find_noti_cb(struct noti *noti, vconf_callback_fn cb)
@@ -682,10 +704,10 @@ EXPORT int vconf_notify_key_changed(const char *key, vconf_callback_fn cb,
                return -1;
        }
 
-       pthread_mutex_lock(&vconf_lock);
+       _vconf_mutex_lock();
        r = _vconf_con_open();
        if (r != 0) {
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                VCONF_SET_ERRNO(r);
                return -1;
        }
@@ -695,7 +717,7 @@ EXPORT int vconf_notify_key_changed(const char *key, vconf_callback_fn cb,
                r = _vconf_create_noti(key, cb, user_data, &noti);
                if (r != 0) {
                        _vconf_con_close();
-                       pthread_mutex_unlock(&vconf_lock);
+                       _vconf_mutex_unlock();
                        VCONF_SET_ERRNO(r);
                        return -1;
                }
@@ -715,7 +737,7 @@ EXPORT int vconf_notify_key_changed(const char *key, vconf_callback_fn cb,
        }
 
        _vconf_con_close();
-       pthread_mutex_unlock(&vconf_lock);
+       _vconf_mutex_unlock();
 
        if (r != 0) {
                VCONF_SET_ERRNO(r);
@@ -755,10 +777,10 @@ EXPORT int vconf_ignore_key_changed(const char *key, vconf_callback_fn cb)
                return -1;
        }
 
-       pthread_mutex_lock(&vconf_lock);
+       _vconf_mutex_lock();
        r = _vconf_con_open();
        if (r != 0) {
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                VCONF_SET_ERRNO(r);
                return -1;
        }
@@ -766,7 +788,7 @@ EXPORT int vconf_ignore_key_changed(const char *key, vconf_callback_fn cb)
        noti = g_hash_table_lookup(noti_tbl, key);
        if (!noti) {
                _vconf_con_close();
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                VCONF_SET_ERRNO(ENOENT);
                return -1;
        }
@@ -774,7 +796,7 @@ EXPORT int vconf_ignore_key_changed(const char *key, vconf_callback_fn cb)
        noticb = _vconf_find_noti_cb(noti, cb);
        if (!noticb || !noticb->active) {
                _vconf_con_close();
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                VCONF_SET_ERRNO(ENOENT);
                return -1;
        }
@@ -789,7 +811,7 @@ EXPORT int vconf_ignore_key_changed(const char *key, vconf_callback_fn cb)
 
        if (cnt > 0) {
                _vconf_con_close();
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                return 0;
        }
 
@@ -807,7 +829,7 @@ EXPORT int vconf_ignore_key_changed(const char *key, vconf_callback_fn cb)
        /* decrease reference count */
        _vconf_con_close();
 
-       pthread_mutex_unlock(&vconf_lock);
+       _vconf_mutex_unlock();
        return 0;
 }
 
@@ -815,10 +837,10 @@ static int _vconf_set(const char *key, const struct buxton_value *val)
 {
        int r;
 
-       pthread_mutex_lock(&vconf_lock);
+       _vconf_mutex_lock();
        r = _vconf_con_open();
        if (r != 0) {
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                return r;
        }
 
@@ -829,7 +851,7 @@ static int _vconf_set(const char *key, const struct buxton_value *val)
        }
 
        _vconf_con_close();
-       pthread_mutex_unlock(&vconf_lock);
+       _vconf_mutex_unlock();
 
        return r;
 }
@@ -955,10 +977,10 @@ static int _vconf_get(const char *key, enum buxton_key_type type,
        int r;
        struct buxton_value *v;
 
-       pthread_mutex_lock(&vconf_lock);
+       _vconf_mutex_lock();
        r = _vconf_con_open();
        if (r != 0) {
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                return r;
        }
 
@@ -984,7 +1006,7 @@ static int _vconf_get(const char *key, enum buxton_key_type type,
        }
 
        _vconf_con_close();
-       pthread_mutex_unlock(&vconf_lock);
+       _vconf_mutex_unlock();
 
        return r;
 }
@@ -1536,10 +1558,10 @@ EXPORT int vconf_get(keylist_t *keylist,
                return -1;
        }
 
-       pthread_mutex_lock(&vconf_lock);
+       _vconf_mutex_lock();
        r = _vconf_con_open();
        if (r != 0) {
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                VCONF_SET_ERRNO(r);
                return -1;
        }
@@ -1549,7 +1571,7 @@ EXPORT int vconf_get(keylist_t *keylist,
                r = buxton_err_get_errno();
                LOGE("get key list: errno %d", r);
                _vconf_con_close();
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                VCONF_SET_ERRNO(r);
                return -1;
        }
@@ -1571,7 +1593,7 @@ EXPORT int vconf_get(keylist_t *keylist,
        buxton_free_keys(names);
 
        _vconf_con_close();
-       pthread_mutex_unlock(&vconf_lock);
+       _vconf_mutex_unlock();
 
        return 0;
 }
@@ -1629,10 +1651,10 @@ EXPORT int vconf_unset(const char *in_key)
                return -1;
        }
 
-       pthread_mutex_lock(&vconf_lock);
+       _vconf_mutex_lock();
        r = _vconf_con_open();
        if (r != 0) {
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                VCONF_SET_ERRNO(r);
                return -1;
        }
@@ -1640,7 +1662,7 @@ EXPORT int vconf_unset(const char *in_key)
        r = buxton_unset_value_sync(client, _vconf_get_layer(in_key), in_key);
 
        _vconf_con_close();
-       pthread_mutex_unlock(&vconf_lock);
+       _vconf_mutex_unlock();
 
        if (r != 0) {
                r = buxton_err_get_errno();
@@ -1678,10 +1700,10 @@ EXPORT int vconf_unset_recursive(const char *in_dir)
                return -1;
        }
 
-       pthread_mutex_lock(&vconf_lock);
+       _vconf_mutex_lock();
        r = _vconf_con_open();
        if (r != 0) {
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                VCONF_SET_ERRNO(r);
                return -1;
        }
@@ -1691,7 +1713,7 @@ EXPORT int vconf_unset_recursive(const char *in_dir)
                r = buxton_err_get_errno();
                LOGE("get key list: errno %d", r);
                _vconf_con_close();
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                VCONF_SET_ERRNO(r);
                return -1;
        }
@@ -1700,20 +1722,20 @@ EXPORT int vconf_unset_recursive(const char *in_dir)
                if (strncmp(in_dir, names[i], dirlen))
                        continue;
 
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                r = vconf_unset(names[i]);
-               pthread_mutex_lock(&vconf_lock);
+               _vconf_mutex_lock();
                if (r != 0) {
                        buxton_free_keys(names);
                        _vconf_con_close();
-                       pthread_mutex_unlock(&vconf_lock);
+                       _vconf_mutex_unlock();
                        return -1;
                }
        }
 
        buxton_free_keys(names);
        _vconf_con_close();
-       pthread_mutex_unlock(&vconf_lock);
+       _vconf_mutex_unlock();
        /* LCOV_EXCL_STOP */
 
        return 0;
@@ -1730,10 +1752,10 @@ EXPORT int vconf_sync_key(const char *in_key)
                return -1;
        }
 
-       pthread_mutex_lock(&vconf_lock);
+       _vconf_mutex_lock();
        r = _vconf_con_open();
        if (r != 0) {
-               pthread_mutex_unlock(&vconf_lock);
+               _vconf_mutex_unlock();
                VCONF_SET_ERRNO(r);
                return -1;
        }
@@ -1741,7 +1763,7 @@ EXPORT int vconf_sync_key(const char *in_key)
        r = buxton_get_value_sync(client, _vconf_get_layer(in_key), in_key, &v);
 
        _vconf_con_close();
-       pthread_mutex_unlock(&vconf_lock);
+       _vconf_mutex_unlock();
 
        if (r != 0) {
                r = buxton_err_get_errno();