Fix potential race condition problem 29/196929/2
authorSangyoon Jang <jeremy.jang@samsung.com>
Tue, 8 Jan 2019 04:37:29 +0000 (13:37 +0900)
committerSangyoon Jang <jeremy.jang@samsung.com>
Tue, 8 Jan 2019 04:48:36 +0000 (13:48 +0900)
There was a potential race condition because of using global hash table
for storing getsize callback information. The getsize can be invoked by
multiple thread in same time, so this global hashtable should be removed.

Change-Id: I78ff68c085f73031a7fb76ace660cf3c497519f0
Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
src/package_manager.c

index 83b789e..bce3f8c 100644 (file)
@@ -28,8 +28,6 @@
 #include "package_manager.h"
 #include "package_manager_internal.h"
 
-static GHashTable *__cb_table = NULL;
-
 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
 typedef struct _request_event_info {
        int req_id;
@@ -1532,23 +1530,25 @@ API int package_manager_clear_all_cache_dir(void)
        return package_manager_clear_cache_dir(PKG_CLEAR_ALL_CACHE);
 }
 
-static void __free_client(gpointer data)
-{
-       pkgmgr_client *pc = (pkgmgr_client *)data;
-       pkgmgr_client_free(pc);
-}
+struct getsize_cbdata {
+       pkgmgr_client *pc;
+       void *cb;
+       void *user_data;
+};
 
-static void __initialize_cb_table(void)
+static void __free_getsize_cbdata(struct getsize_cbdata *cbdata)
 {
-       __cb_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, __free_client, NULL);
+       pkgmgr_client_free(cbdata->pc);
+       free(cbdata);
 }
 
 static void __result_cb(pkgmgr_client *pc, const char *pkgid, const pkg_size_info_t *result, void *user_data)
 {
-       package_manager_size_info_receive_cb callback = g_hash_table_lookup(__cb_table, pc);
+       struct getsize_cbdata *cbdata = (struct getsize_cbdata *)user_data;
+       package_manager_size_info_receive_cb callback = cbdata->cb;
        if (callback == NULL) {
                _LOGE("callback is null.");
-               g_hash_table_remove(__cb_table, pc);
+               __free_getsize_cbdata(cbdata);
                return;
        }
 
@@ -1562,15 +1562,16 @@ static void __result_cb(pkgmgr_client *pc, const char *pkgid, const pkg_size_inf
 
        callback(pkgid, (package_size_info_h)&size_info, user_data);
 
-       g_hash_table_remove(__cb_table, pc);
+       __free_getsize_cbdata(cbdata);
 }
 
 static void __total_result_cb(pkgmgr_client *pc, const pkg_size_info_t *result, void *user_data)
 {
-       package_manager_total_size_info_receive_cb callback = g_hash_table_lookup(__cb_table, pc);
+       struct getsize_cbdata *cbdata = (struct getsize_cbdata *)user_data;
+       package_manager_total_size_info_receive_cb callback = cbdata->cb;
        if (callback == NULL) {
                _LOGE("callback is null.");
-               g_hash_table_remove(__cb_table, pc);
+               __free_getsize_cbdata(cbdata);
                return;
        }
 
@@ -1584,26 +1585,35 @@ static void __total_result_cb(pkgmgr_client *pc, const pkg_size_info_t *result,
 
        callback((package_size_info_h)&size_info, user_data);
 
-       g_hash_table_remove(__cb_table, pc);
+       __free_getsize_cbdata(cbdata);
 }
 
 static int _get_pkg_size_info(const char *package_id, void *callback, void *user_data)
 {
+       struct getsize_cbdata *cbdata;
+
        if (package_id == NULL || callback == NULL)
                return package_manager_error(PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
 
-       if (__cb_table == NULL)
-               __initialize_cb_table();
+       cbdata = malloc(sizeof(struct getsize_cbdata));
+       if (cbdata == NULL)
+               return package_manager_error(PACKAGE_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
 
        pkgmgr_client *pc = pkgmgr_client_new(PC_REQUEST);
-       if (pc == NULL)
+       if (pc == NULL) {
+               free(cbdata);
                return package_manager_error(PACKAGE_MANAGER_ERROR_SYSTEM_ERROR, __FUNCTION__, NULL);
+       }
+
+       cbdata->pc = pc;
+       cbdata->cb = callback;
+       cbdata->user_data = user_data;
 
        int res = 0;
        if (strcmp(package_id, PKG_SIZE_INFO_TOTAL) != 0)
-               res = pkgmgr_client_get_package_size_info(pc, package_id, __result_cb, user_data);
+               res = pkgmgr_client_get_package_size_info(pc, package_id, __result_cb, cbdata);
        else
-               res = pkgmgr_client_get_total_package_size_info(pc, __total_result_cb, user_data);
+               res = pkgmgr_client_get_total_package_size_info(pc, __total_result_cb, cbdata);
 
        if (res == PKGMGR_R_EINVAL) {
                pkgmgr_client_free(pc);
@@ -1625,12 +1635,10 @@ static int _get_pkg_size_info(const char *package_id, void *callback, void *user
                return package_manager_error(PACKAGE_MANAGER_ERROR_SYSTEM_ERROR, __FUNCTION__, NULL);
        } else if (res != PKGMGR_R_OK) {
                _LOGE("Unexpected error");
-               pkgmgr_client_free(pc);
+               __free_getsize_cbdata(cbdata);
                return package_manager_error(PACKAGE_MANAGER_ERROR_SYSTEM_ERROR, __FUNCTION__, NULL);
        }
 
-       g_hash_table_insert(__cb_table, pc, callback);
-
        return PACKAGE_MANAGER_ERROR_NONE;
 }