From e5ad7ef49aee949838cfca14e45ff0f3cdf8ffc5 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Tue, 5 Nov 2024 17:39:10 +0900 Subject: [PATCH] Add defensive code to avoid crash - The user callback can be called in __camera_idle_event_callback() although handle is destroyed after g_cam_idle_event_lock is unlocked. - Add new flag to avoid that situation. [Version] 1.2.1 [Issue Type] Improvement Change-Id: I965f07768a18cdd82e460b10b3db6cedf626d3f4 Signed-off-by: Jeongmo Yang --- include/camera_private.h | 1 + packaging/capi-media-camera.spec | 2 +- src/camera.c | 38 +++++++++++++++++++++++--------- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/include/camera_private.h b/include/camera_private.h index bd26435..bc082ea 100644 --- a/include/camera_private.h +++ b/include/camera_private.h @@ -187,6 +187,7 @@ typedef struct _camera_cb_info_s { gpointer user_data[MUSE_CAMERA_EVENT_TYPE_NUM]; GMutex user_cb_lock[MUSE_CAMERA_EVENT_TYPE_NUM]; gboolean invoke_preview_cb; + gboolean is_in_idle_cb; /* tbm */ tbm_bufmgr bufmgr; diff --git a/packaging/capi-media-camera.spec b/packaging/capi-media-camera.spec index ee0fb19..40e8899 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: 1.2.0 +Version: 1.2.1 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/camera.c b/src/camera.c index 387b50a..07d4d5f 100644 --- a/src/camera.c +++ b/src/camera.c @@ -1752,7 +1752,6 @@ static gboolean __camera_idle_event_callback(gpointer data) cb_info = cam_idle_event->cb_info; if (cb_info == NULL) { CAM_LOG_WARNING("NULL cb_info for event[%d] %p", cam_idle_event->event, cam_idle_event); - g_mutex_unlock(&g_cam_idle_event_lock); goto IDLE_EVENT_CALLBACK_DONE; } @@ -1760,12 +1759,20 @@ static gboolean __camera_idle_event_callback(gpointer data) if (cb_info->idle_event_list) cb_info->idle_event_list = g_list_remove(cb_info->idle_event_list, (gpointer)cam_idle_event); + cb_info->is_in_idle_cb = TRUE; + g_mutex_unlock(&g_cam_idle_event_lock); /* user callback */ __camera_client_user_callback(cb_info, cam_idle_event->recv_msg, cam_idle_event->event, cam_idle_event->tfd); + g_mutex_lock(&g_cam_idle_event_lock); + + cb_info->is_in_idle_cb = FALSE; + IDLE_EVENT_CALLBACK_DONE: + g_mutex_unlock(&g_cam_idle_event_lock); + /* release event */ g_free(cam_idle_event); @@ -1920,7 +1927,6 @@ static void __camera_deactivate_idle_event_all(camera_cb_info_s *cb_info) { camera_idle_event_s *cam_idle_event = NULL; GList *list = NULL; - g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&g_cam_idle_event_lock); if (cb_info == NULL) { CAM_LOG_ERROR("cb_info is NULL"); @@ -1939,7 +1945,7 @@ static void __camera_deactivate_idle_event_all(camera_cb_info_s *cb_info) list = g_list_next(list); if (!cam_idle_event) { - CAM_LOG_WARNING("Fail to remove idle event. The event is NULL"); + CAM_LOG_WARNING("The event is NULL"); continue; } @@ -2871,26 +2877,36 @@ int camera_destroy(camera_h camera) int ret = CAMERA_ERROR_NONE; muse_camera_api_e api = MUSE_CAMERA_API_DESTROY; camera_cli_s *pc = (camera_cli_s *)camera; + g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&g_cam_idle_event_lock); CAMERA_CHECK_HANDLE_RETURN_VAL(pc, CAMERA_ERROR_INVALID_PARAMETER); CAM_LOG_INFO("Enter"); + if (pc->cb_info->is_in_idle_cb) { + CAM_LOG_ERROR("should not be called in idle callback"); + return CAMERA_ERROR_INVALID_OPERATION; + } + if (pc->cb_info->is_server_connected) _camera_msg_send(api, NULL, pc->cb_info, &ret, CAMERA_CB_TIMEOUT); else CAM_LOG_WARNING("server disconnected. release resource without send message."); - if (ret == CAMERA_ERROR_NONE) { - __camera_deactivate_idle_event_all(pc->cb_info); - __camera_client_callback_destroy(pc->cb_info); - pc->cb_info = NULL; - - g_free(pc); - pc = NULL; + if (ret != CAMERA_ERROR_NONE) { + CAM_LOG_ERROR("handle destroy failed[0x%x]", ret); + return ret; } - CAM_LOG_INFO("ret : 0x%x", ret); + __camera_deactivate_idle_event_all(pc->cb_info); + + g_clear_pointer(&locker, g_mutex_locker_free); + + __camera_client_callback_destroy(pc->cb_info); + + g_free(pc); + + CAM_LOG_INFO("done"); return ret; } -- 2.34.1