fix up! Remove thread for preview callback when stop preview 09/269109/2 accepted/tizen/unified/20220111.123039 submit/tizen/20220110.092727
authorJeongmo Yang <jm80.yang@samsung.com>
Mon, 10 Jan 2022 02:40:15 +0000 (11:40 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Mon, 10 Jan 2022 03:22:48 +0000 (12:22 +0900)
- The thread leak is occurred with below sequence and it causes deadlock after some time.
 1. Process A calls camera_start_preview(). -> create thread for preview callback
 2. Process B calls camera_start_preview().
 3. Process A gets interrupted callback and the state of camera handle is changed to CAMERA_STATE_CREATED.
    Then, process A's preview callback thread is remained, because it is released in camera_stop_preview(),
    but, it's skipped by interrupt.

[Version] 0.4.71
[Issue Type] Bug fix

Change-Id: Ifaafb52ed3e549d3a6203754ec6fa90079893cb5
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
packaging/capi-media-camera.spec
src/camera.c

index 74a4cd2..495fc0e 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-camera
 Summary:    A Camera API
-Version:    0.4.70
+Version:    0.4.71
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index d7e0dc0..46679c0 100644 (file)
@@ -56,6 +56,10 @@ static gboolean __camera_allocate_preview_buffer(camera_h camera);
 static void __camera_release_preview_buffer(camera_h camera);
 static void __camera_release_tfd(int tfd[MUSE_NUM_FD]);
 
+static bool __create_msg_handler_thread(camera_msg_handler_info_s *handler_info,
+       int type, const char *thread_name, camera_cb_info_s *cb_info);
+static void __destroy_msg_handler_thread(camera_msg_handler_info_s *handler_info);
+
 
 static gboolean __camera_allocate_preview_buffer(camera_h camera)
 {
@@ -1599,7 +1603,7 @@ static gpointer __camera_msg_handler_func(gpointer data)
        cb_info = (camera_cb_info_s *)handler_info->cb_info;
        type = handler_info->type;
 
-       CAM_LOG_INFO("t:%d start", type);
+       CAM_LOG_INFO("t:%d start[thread:%p]", type, handler_info->thread);
 
        g_mutex_lock(&handler_info->mutex);
 
@@ -1649,6 +1653,11 @@ static gpointer __camera_msg_handler_func(gpointer data)
 
                        g_mutex_unlock(&cb_info->api_mutex[api]);
                } else if (api == MUSE_CAMERA_CB_EVENT) {
+                       if (cam_msg->event == MUSE_CAMERA_EVENT_TYPE_INTERRUPTED) {
+                               CAM_LOG_WARNING("INTERRUPTED, release thread for preview cb");
+                               __destroy_msg_handler_thread(&cb_info->preview_cb_info);
+                       }
+
                        switch (cam_msg->event_class) {
                        case MUSE_CAMERA_EVENT_CLASS_THREAD_SUB:
                                __camera_client_user_callback(cb_info, cam_msg->recv_msg, cam_msg->event, cam_msg->tfd);
@@ -1706,7 +1715,7 @@ static gpointer __camera_msg_handler_func(gpointer data)
 
        g_mutex_unlock(&handler_info->mutex);
 
-       CAM_LOG_INFO("t:%d return", type);
+       CAM_LOG_INFO("t:%d return[thread:%p]", type, handler_info->thread);
 
        return NULL;
 }
@@ -2040,6 +2049,11 @@ static bool __create_msg_handler_thread(camera_msg_handler_info_s *handler_info,
                return false;
        }
 
+       if (handler_info->thread) {
+               CAM_LOG_WARNING("t:%d thread[%p] is already created", type, handler_info->thread);
+               return true;
+       }
+
        CAM_LOG_INFO("t:%d [%s]", type, thread_name);
 
        handler_info->type = type;
@@ -2068,7 +2082,7 @@ static bool __create_msg_handler_thread(camera_msg_handler_info_s *handler_info,
                return false;
        }
 
-       CAM_LOG_INFO("t:%d done", type);
+       CAM_LOG_INFO("t:%d done[thread:%p]", type, handler_info->thread);
 
        return true;
 }
@@ -2090,7 +2104,7 @@ static void __destroy_msg_handler_thread(camera_msg_handler_info_s *handler_info
 
        type = handler_info->type;
 
-       CAM_LOG_INFO("t:%d thread %p", type, handler_info->thread);
+       CAM_LOG_INFO("t:%d thread[%p]", type, handler_info->thread);
 
        g_mutex_lock(&handler_info->mutex);
        g_atomic_int_set(&handler_info->running, 0);
@@ -2208,6 +2222,8 @@ static void __camera_client_callback_destroy(camera_cb_info_s *cb_info)
        CAM_LOG_INFO("msg_recv thread removed");
 
        /* destroy msg handler threads */
+       if (cb_info->preview_cb_info.thread)
+               __destroy_msg_handler_thread(&cb_info->preview_cb_info);
        __destroy_msg_handler_thread(&cb_info->msg_handler_info);
        __destroy_msg_handler_thread(&cb_info->capture_cb_info);