From: Jeongmo Yang Date: Mon, 10 Jan 2022 02:40:15 +0000 (+0900) Subject: fix up! Remove thread for preview callback when stop preview X-Git-Tag: accepted/tizen/unified/20220111.123039^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F09%2F269109%2F2;p=platform%2Fcore%2Fapi%2Fcamera.git fix up! Remove thread for preview callback when stop preview - 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 --- diff --git a/packaging/capi-media-camera.spec b/packaging/capi-media-camera.spec index 74a4cd2..495fc0e 100644 --- a/packaging/capi-media-camera.spec +++ b/packaging/capi-media-camera.spec @@ -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 diff --git a/src/camera.c b/src/camera.c index d7e0dc0..46679c0 100644 --- a/src/camera.c +++ b/src/camera.c @@ -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);