wayland-client: add mutex protection to destroy_thread_data
authorJoonbum Ko <joonbum.ko@samsung.com>
Wed, 29 Dec 2021 02:06:04 +0000 (11:06 +0900)
committerJunkyeong Kim <jk0430.kim@samsung.com>
Thu, 16 Feb 2023 10:22:35 +0000 (19:22 +0900)
 In multi threads situation,
 at the same time that the newly created thread performs
 wl_list_for_each_safe() in get_thread_data(),
 the destroyed thread may cause a conflict problem
 in an attempt to erase its link with wl_list_remove.

 Added threads_mutex to struct wl_display to protect
  accessing display->threads.

Change-Id: I673c3f9a63794d514e871839049257425bd06bc2
Signed-off-by: Joonbum Ko <joonbum.ko@samsung.com>
src/wayland-client.c

index 49e646e..512cbf3 100644 (file)
@@ -154,6 +154,7 @@ struct wl_display {
 
        pthread_key_t thread_data_key;
        struct wl_list  threads;
+       pthread_mutex_t threads_mutex;
 // TIZEN_ONLY(20190716) : wayland-client : force sync of display when threads are waiting for over WL_PTHREAD_COND_TIMEDWAIT_TIMEOUT
        uint32_t force_sync_count;
 // END
@@ -1199,6 +1200,7 @@ destroy_thread_data(void *data)
        display = thread_data->display;
        assert(display);
 
+       pthread_mutex_lock(&display->threads_mutex);
        wl_list_remove(&thread_data->link);
        display->threads_count--;
        wl_log("Thread removed[%p pid:%d tid: %d] from display:%p, threads_cnt=%d\n",
@@ -1212,6 +1214,7 @@ destroy_thread_data(void *data)
                        thread_data->pid, thread_data->tid, display->reader_count, thread_data->reader_count_in_thread);
                wl_log("######################################################################\n");
        }
+       pthread_mutex_unlock(&display->threads_mutex);
 
        free(thread_data);
 }
@@ -1226,6 +1229,7 @@ get_thread_data(struct wl_display *display)
        int tid = (int)syscall(SYS_gettid);
 
        thread_data = pthread_getspecific(display->thread_data_key);
+       pthread_mutex_lock(&display->threads_mutex);
        if (!thread_data && display->threads_count > 0) {
                wl_list_for_each_safe(th_data, tmp, &display->threads, link) {
                        if (th_data && th_data->pid == pid && th_data->tid == tid) {
@@ -1235,6 +1239,7 @@ get_thread_data(struct wl_display *display)
                        }
                }
        }
+       pthread_mutex_unlock(&display->threads_mutex);
 
        if (!thread_data) {
                int ret = 0;
@@ -1254,9 +1259,11 @@ get_thread_data(struct wl_display *display)
                thread_data->state = WL_THREAD_STATE_INITIAL;
                thread_data->thread_id = pthread_self();
 // END
+               pthread_mutex_lock(&display->threads_mutex);
                wl_list_init(&thread_data->link);
                wl_list_insert(&display->threads, &thread_data->link);
                display->threads_count++;
+               pthread_mutex_unlock(&display->threads_mutex);
                wl_log("Thread added[%p, pid:%d tid: %d] to display:%p, threads_cnt=%d, errno(%d, %m)\n",
                        thread_data, thread_data->pid, thread_data->tid, display, display->threads_count, errno);
        }
@@ -1499,6 +1506,7 @@ wl_display_connect_to_fd(int fd)
 
        display->threads_count = 0;
        wl_list_init(&display->threads);
+       pthread_mutex_init(&display->threads_mutex, NULL);
        if (pthread_key_create(&display->thread_data_key, destroy_thread_data) < 0)
                goto err_connection;
 
@@ -1512,10 +1520,10 @@ wl_display_connect_to_fd(int fd)
                        display, &display->default_queue, &display->display_queue, display->fd);
 #endif
 
-       pthread_mutex_unlock(&display->mutex);
-
        wl_log("display(%p) connected. (pid:%d, tid:%d, threads_cnt=%d, reader_cnt=%d)\n",
                display, thread_data->pid, thread_data->tid, display->threads_count, display->reader_count);
+       
+       pthread_mutex_unlock(&display->mutex);
 
        return display;
 
@@ -2016,12 +2024,14 @@ _check_reader_counts(struct wl_display *display)
 
        wl_log("[check_reader_counts] Number of threads=%d, reader_count=%d\n", display->threads_count, display->reader_count);
 
+       pthread_mutex_lock(&display->threads_mutex);
        wl_list_for_each_safe(th_data, th_data_next, &display->threads, link) {
                wl_log("... thread[%d]:reader_count_in_thread=%d\n", cnt++, th_data->reader_count_in_thread);
 
                if (th_data->reader_count_in_thread > 0)
                        threads_reader_counts++;
        }
+       pthread_mutex_unlock(&display->threads_mutex);
 
        if (threads_reader_counts < display->reader_count)
        {
@@ -2048,10 +2058,12 @@ log_threads_reader_info(struct wl_display *display)
        wl_log("[thread info] current pid : %d, tid : %d\n", thread_data->pid, thread_data->tid);
        wl_log("[thread info] display->reader_count : %d\n", display->reader_count);
 
+       pthread_mutex_lock(&display->threads_mutex);
        wl_list_for_each_safe(th_data, th_data_next, &display->threads, link) {
                wl_log("[thread info] thread[%d][PID:%d][TID:%d][id:%lu] reader_count_in_thread:%d, state:%d\n",
                                thread_cnt++, th_data->pid, th_data->tid, th_data->thread_id, th_data->reader_count_in_thread, th_data->state);
        }
+       pthread_mutex_unlock(&display->threads_mutex);
 }
 
 static void