extend lock in buxton_open_full 09/103709/3 submit/tizen_3.0/20161213.042049
authorJiwoong Im <jiwoong.im@samsung.com>
Fri, 9 Dec 2016 07:54:26 +0000 (16:54 +0900)
committerJiwoong Im <jiwoong.im@samsung.com>
Mon, 12 Dec 2016 00:46:56 +0000 (09:46 +0900)
- If call free_client function without taking lock,
  it can cause an infinite loop in recv_cb.

Change-Id: I7ebf99c0eb745e142a0e3b0ebb4bb4fc4f5e7eb8
Signed-off-by: Jiwoong Im <jiwoong.im@samsung.com>
lib/buxton2.c

index bbe1584..d9d9dd9 100644 (file)
@@ -2309,6 +2309,8 @@ static gboolean close_conn(gpointer data)
 {
        struct buxton_client *cli = data;
        GList *f;
+       buxton_status_callback callback = NULL;
+       void * user_data;
 
        assert(cli);
 
@@ -2332,9 +2334,15 @@ static gboolean close_conn(gpointer data)
 
        close(cli->fd);
        cli->fd = -1;
+
+       if (cli->st_callback) {
+               callback = cli->st_callback;
+               user_data = cli->st_data;
+       }
        pthread_mutex_unlock(&clients_lock);
-       if (cli->st_callback)
-               cli->st_callback(BUXTON_STATUS_CONNECTION_CLOSED, cli->st_data);
+
+       if (callback)
+               callback(BUXTON_STATUS_CONNECTION_CLOSED, user_data);
 
        return G_SOURCE_REMOVE;
 }
@@ -2422,7 +2430,7 @@ static gboolean recv_cb(gint fd, GIOCondition cond, gpointer data)
        if (!f) {
                bxt_dbg("recv %d: cli %p removed\n", fd, cli);
                pthread_mutex_unlock(&clients_lock);
-               return G_SOURCE_CONTINUE;
+               return G_SOURCE_REMOVE;
        }
 
        bxt_dbg("recv %d: cond %x", fd, cond);
@@ -2481,6 +2489,7 @@ EXPORT int buxton_open_full(struct buxton_client **client, bool attach_fd,
                return -1;
        }
 
+       pthread_mutex_lock(&clients_lock);
        cli = calloc(1, sizeof(*cli));
        if (!cli)
                return -1;
@@ -2497,6 +2506,7 @@ EXPORT int buxton_open_full(struct buxton_client **client, bool attach_fd,
                pthread_mutex_unlock(&cli->lock);
                free_client(cli);
                errno = ENOMEM;
+               pthread_mutex_unlock(&clients_lock);
                return -1;
        }
        cli->noti_cbs = g_hash_table_new_full(g_str_hash, g_str_equal,
@@ -2505,6 +2515,7 @@ EXPORT int buxton_open_full(struct buxton_client **client, bool attach_fd,
                pthread_mutex_unlock(&cli->lock);
                free_client(cli);
                errno = ENOMEM;
+               pthread_mutex_unlock(&clients_lock);
                return -1;
        }
        pthread_mutex_unlock(&cli->lock);
@@ -2512,6 +2523,7 @@ EXPORT int buxton_open_full(struct buxton_client **client, bool attach_fd,
        cli->fd = connect_server(SOCKPATH);
        if (cli->fd == -1) {
                free_client(cli);
+               pthread_mutex_unlock(&clients_lock);
                return -1;
        }
 
@@ -2522,10 +2534,9 @@ EXPORT int buxton_open_full(struct buxton_client **client, bool attach_fd,
        else
                cli->fd_id = 0;
 
-       pthread_mutex_lock(&clients_lock);
        clients = g_list_append(clients, cli);
-       pthread_mutex_unlock(&clients_lock);
        *client = cli;
+       pthread_mutex_unlock(&clients_lock);
 
        if (callback)
                callback(BUXTON_STATUS_CONNECTED, user_data);