From 72d7bd5fca1262d23e39c9b797226638694d30cf Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Fri, 18 Nov 2022 20:15:09 +0900 Subject: focus_socket: wait for socket listen ready In addition, client retry added for abnormal socket condition [Version] 0.13.23 [Issue Type] Update Change-Id: I3e18abaffa0ffae8472d58f2e593e5ab76a610ad --- focus_server/include/mm_sound_mgr_focus_socket.h | 28 +++- focus_server/mm_sound_focus_server.c | 11 +- focus_server/mm_sound_mgr_focus_socket.c | 177 +++++++++++++++++------ mm_sound_focus_socket.c | 26 +++- packaging/libmm-sound.spec | 2 +- 5 files changed, 184 insertions(+), 60 deletions(-) diff --git a/focus_server/include/mm_sound_mgr_focus_socket.h b/focus_server/include/mm_sound_mgr_focus_socket.h index 9768c48..2a0e67d 100644 --- a/focus_server/include/mm_sound_mgr_focus_socket.h +++ b/focus_server/include/mm_sound_mgr_focus_socket.h @@ -1,9 +1,29 @@ +/* + * libmm-sound + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Sangchul Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + #ifndef __MM_SOUND_MGR_FOCUS_SOCKET_H__ #define __MM_SOUND_MGR_FOCUS_SOCKET_H__ -int MMSoundMgrFocusSocketInit(int *fd); -void MMSoundMgrFocusSocketFini(int fd); -int MMSoundMgrFocusSocketReadyToWork(int fd); - +int MMSoundMgrFocusSocketInit(int *sockfd); +void MMSoundMgrFocusSocketFini(int *sockfd); +int MMSoundMgrFocusSocketReadyToWork(const int *sockfd); #endif /* __MM_SOUND_MGR_FOCUS_SOCKET_H__ */ diff --git a/focus_server/mm_sound_focus_server.c b/focus_server/mm_sound_focus_server.c index f6adf8f..3d7a581 100644 --- a/focus_server/mm_sound_focus_server.c +++ b/focus_server/mm_sound_focus_server.c @@ -141,7 +141,7 @@ static void _signal_handler(int signo) MMSoundMgrFocusDbusFini(); MMSoundMgrFocusFini(); - MMSoundMgrFocusSocketFini(g_socket_fd); + MMSoundMgrFocusSocketFini(&g_socket_fd); #ifdef USE_GCOV mm_sound_gcov_flush(); @@ -219,8 +219,6 @@ int main(int argc, char **argv) #if !defined(USE_SYSTEM_SERVER_PROCESS_MONITORING) int pid; #endif - int socket_fd = -1; - if (_get_option(argc, argv, &serveropt)) return 1; @@ -263,17 +261,16 @@ int main(int argc, char **argv) /* Change the file mode mask */ umask(0); - if (MMSoundMgrFocusSocketInit(&socket_fd)) { + if (MMSoundMgrFocusSocketInit(&g_socket_fd)) { debug_error("focus_server [%d] terminating, due to the error of socket init.", getpid()); return 0; } - if (MMSoundMgrFocusSocketReadyToWork(socket_fd)) { + if (MMSoundMgrFocusSocketReadyToWork(&g_socket_fd)) { debug_error("focus_server [%d] terminating, due to the error of thread init.", getpid()); return 0; } MMSoundMgrFocusDbusInit(); MMSoundMgrFocusInit(); - g_socket_fd = socket_fd; } debug_warning("focus_server [%d] initialization complete...now, start running!!", getpid()); @@ -301,7 +298,7 @@ int main(int argc, char **argv) if (serveropt.startserver) { MMSoundMgrFocusDbusFini(); MMSoundMgrFocusFini(); - MMSoundMgrFocusSocketFini(socket_fd); + MMSoundMgrFocusSocketFini(&g_socket_fd); } _signal_finalize(); diff --git a/focus_server/mm_sound_mgr_focus_socket.c b/focus_server/mm_sound_mgr_focus_socket.c index a06800d..162c552 100644 --- a/focus_server/mm_sound_mgr_focus_socket.c +++ b/focus_server/mm_sound_mgr_focus_socket.c @@ -62,6 +62,15 @@ enum { FOCUS_FUNCTION_MAX, }; +#define DEFAULT_FOCUS_THREAD_READY_TIMEOUT 5 + +typedef struct mm_sound_focus_thread_data { + const int *sockfd; + GMutex wait_mutex; + GCond wait_cond; + gboolean listen_ready; +} focus_thread_data_t; + typedef struct mm_sound_focus_function_intf { const char *name; focus_function_handler handler; @@ -266,7 +275,7 @@ static int focus_functions_handler(int fd, _mm_sound_focus_socket_param_t *param if (param == NULL) return MM_ERROR_INVALID_ARGUMENT; - debug_log("fd[%d], param[%p], function_name[%s]", fd, param, param->func_name); + debug_msg("fd[%d], param[%p], function_name[%s]", fd, param, param->func_name); for (i = 0; i < FOCUS_FUNCTION_MAX; i++) { if (!strncmp(param->func_name, functions[i].name, MAX_ERROR_LEN)) @@ -286,7 +295,68 @@ static bool need_to_exit(const char *func_name) return false; } -static void* work_thread_func(void *data) + +static focus_thread_data_t *__focus_thread_data_create(const int *sockfd) +{ + focus_thread_data_t *thread_data = NULL; + thread_data = g_new0(focus_thread_data_t, 1); + + thread_data->sockfd = sockfd; + g_mutex_init(&thread_data->wait_mutex); + g_cond_init(&thread_data->wait_cond); + thread_data->listen_ready = FALSE; + + return thread_data; +} + +static void __focus_thread_ready_signal(focus_thread_data_t *thread_data) +{ + g_assert(thread_data); + + g_mutex_lock(&thread_data->wait_mutex); + + debug_msg("signaling focus thread ready!"); + thread_data->listen_ready = TRUE; + g_cond_signal(&thread_data->wait_cond); + + g_mutex_unlock(&thread_data->wait_mutex); +} + +static gboolean __focus_thread_ready_wait(focus_thread_data_t *thread_data, int timeout_sec) +{ + gint64 end_time; + g_autoptr(GMutexLocker) locker = NULL; + + g_assert(thread_data); + + locker = g_mutex_locker_new(&thread_data->wait_mutex); + + end_time = g_get_monotonic_time() + timeout_sec * G_TIME_SPAN_SECOND; + + while (!thread_data->listen_ready) { + if (!g_cond_wait_until(&thread_data->wait_cond, + &thread_data->wait_mutex, + end_time)) { + debug_error("timeout!!!"); + break; + } + debug_msg("wait done! ready:%d", thread_data->listen_ready); + } + + return thread_data->listen_ready; +} + +static void __focus_thread_data_destroy(focus_thread_data_t *thread_data) +{ + g_assert(thread_data); + + g_mutex_clear(&thread_data->wait_mutex); + g_cond_clear(&thread_data->wait_cond); + + g_free(thread_data); +} + +static void *work_thread_func(void *data) { int accepted_fd = -1; char str_error[MAX_ERROR_LEN] = {'\0',}; @@ -294,16 +364,16 @@ static void* work_thread_func(void *data) _mm_sound_focus_socket_result_t result; int rval = 0; - if (data == NULL) { + debug_fenter(); + + if (!data) { debug_error("invalid data"); pthread_exit(NULL); } - debug_fenter(); - accepted_fd = (int)(uintptr_t)(data); - do { + while (1) { memset(&read_data, 0x00, sizeof(_mm_sound_focus_socket_param_t)); if ((rval = read(accepted_fd, &read_data, sizeof(_mm_sound_focus_socket_param_t))) < 0) { strerror_r(errno, str_error, sizeof(str_error)); @@ -327,33 +397,36 @@ static void* work_thread_func(void *data) } if (need_to_exit(read_data.func_name)) - goto LEAVE; + break; } else { debug_error("failed to read(), read size mismatched, rval(%d), expect size(%zu)", rval, sizeof(_mm_sound_focus_socket_param_t)); - goto LEAVE; + break; } - } while (1); + } -LEAVE: - debug_fleave(); - debug_log("now close fd[%d]", accepted_fd); /* clean-up FD and focus node */ mm_sound_mgr_focus_emergent_exit_by_id(accepted_fd); + + debug_msg("now close fd[%d]", accepted_fd); close(accepted_fd); + + debug_fleave(); + pthread_exit(NULL); } -static void* ready_thread_func(void *data) +static void *ready_thread_func(void *data) { - int fd = -1; int accepted_fd = -1; char str_error[MAX_ERROR_LEN] = {'\0',}; int ret = 0; pthread_t focus_work_thread_id; pthread_attr_t attr; - if (data == NULL) { + focus_thread_data_t *thread_data = (focus_thread_data_t *)data; + + if (!thread_data) { debug_error("invalid data"); pthread_exit(NULL); } @@ -372,47 +445,48 @@ static void* ready_thread_func(void *data) goto LEAVE; } - fd = (int)(uintptr_t)data; - - if (listen(fd, 5)) { + if (listen(*thread_data->sockfd, 5)) { strerror_r(errno, str_error, sizeof(str_error)); debug_error("failed to listen(), err: %s", str_error); goto LEAVE; } - debug_log("listen for fd [%d] success", fd); + debug_msg("listen for fd [%d] success", *thread_data->sockfd); + + __focus_thread_ready_signal(thread_data); - do { - accepted_fd = accept(fd, NULL, NULL); + while (*thread_data->sockfd != -1) { + accepted_fd = accept(*thread_data->sockfd, NULL, NULL); if (accepted_fd == -1) { strerror_r(errno, str_error, sizeof(str_error)); debug_error("failed to accept(), err: %s", str_error); - goto LEAVE; + break; } debug_log("accepted fd [%d]", accepted_fd); if (pthread_create(&focus_work_thread_id, &attr, (void *)work_thread_func, (void *)(uintptr_t)accepted_fd)) { debug_error("failed to create work thread, accepted_fd(%d)", accepted_fd); - goto LEAVE; + break; } + } - } while (1); + __focus_thread_data_destroy(thread_data); LEAVE: - debug_fleave(); pthread_attr_destroy(&attr); - if (fd != -1) - close(fd); + + debug_fleave(); + pthread_exit(NULL); } -int MMSoundMgrFocusSocketInit(int *fd) +int MMSoundMgrFocusSocketInit(int *sockfd) { int socket_fd; struct sockaddr_un addr_un; char str_error[128] = {'\0',}; - if (fd == NULL) { + if (!sockfd) { debug_error("input param fd is null"); return MM_ERROR_INVALID_ARGUMENT; } @@ -424,7 +498,7 @@ int MMSoundMgrFocusSocketInit(int *fd) goto LEAVE; } - debug_log("focus server socket fd [%d]", socket_fd); + debug_msg("focus server socket fd [%d]", socket_fd); memset(&addr_un, 0, sizeof(addr_un)); addr_un.sun_family = AF_UNIX; @@ -447,9 +521,9 @@ int MMSoundMgrFocusSocketInit(int *fd) } } - debug_log("focus server socket binding success"); + debug_msg("focus server socket binding success"); - *fd = socket_fd; + *sockfd = socket_fd; debug_leave(); @@ -462,38 +536,57 @@ LEAVE: return MM_ERROR_SOUND_INTERNAL; } -void MMSoundMgrFocusSocketFini(int fd) +void MMSoundMgrFocusSocketFini(int *sockfd) { debug_enter(); if (g_focus_ready_thread_id) { unlink(FOCUS_SERVER_SOCK); - shutdown(fd, SHUT_RDWR); - close(fd); + + if (*sockfd != -1) { + shutdown(*sockfd, SHUT_RDWR); + close(*sockfd); + *sockfd = -1; + } + + debug_msg("try pthread join for thread id:%lu", g_focus_ready_thread_id); pthread_join(g_focus_ready_thread_id, NULL); - debug_msg("pthread join well"); + debug_msg("pthread joined well"); g_focus_ready_thread_id = 0; } debug_leave(); } -int MMSoundMgrFocusSocketReadyToWork(int fd) +int MMSoundMgrFocusSocketReadyToWork(const int *sockfd) { debug_enter(); + focus_thread_data_t *thread_data = NULL; - if (fd < 0) { - debug_error("input param fd [%d] is not valid", fd); + if (*sockfd < 0) { + debug_error("input param sockfd [%d] is not valid", *sockfd); return MM_ERROR_INVALID_ARGUMENT; } - debug_log("fd [%d]", fd); - if (pthread_create(&g_focus_ready_thread_id, NULL, (void *)ready_thread_func, (void *)(uintptr_t)fd)) { + debug_msg("sockfd [%d]", *sockfd); + + thread_data = __focus_thread_data_create(sockfd); + + if (pthread_create(&g_focus_ready_thread_id, NULL, (void *)ready_thread_func, thread_data)) { debug_error("failed to create ready thread"); - return MM_ERROR_SOUND_INTERNAL; + goto ERROR_INTERNAL; + } + + if (!__focus_thread_ready_wait(thread_data, DEFAULT_FOCUS_THREAD_READY_TIMEOUT)) { + debug_error("focus thread is not ready for %u sec!!!", DEFAULT_FOCUS_THREAD_READY_TIMEOUT); + goto ERROR_INTERNAL; } debug_leave(); return MM_ERROR_NONE; + +ERROR_INTERNAL: + __focus_thread_data_destroy(thread_data); + return MM_ERROR_SOUND_INTERNAL; } diff --git a/mm_sound_focus_socket.c b/mm_sound_focus_socket.c index 4d8c96f..fa5083c 100644 --- a/mm_sound_focus_socket.c +++ b/mm_sound_focus_socket.c @@ -28,6 +28,9 @@ #include "include/mm_sound_common.h" #include "include/mm_sound_focus_socket.h" +#define MAX_CONNECT_RETRY 10 +#define RETRY_CONNECT_INTERVAL_US 300000 + #define _FILL_SOCKET_PARAM(x_param, x_func_name, x_pid) \ do { \ MMSOUND_STRNCPY(x_param.func_name, x_func_name, MM_SOUND_NAME_NUM); \ @@ -116,6 +119,8 @@ static int _get_client_socket_fd(int *fd) static int _connect_socket_fd(int fd) { + int retry_remaining = MAX_CONNECT_RETRY; + int ret = 0; struct sockaddr_un addr_un; char str_error[128] = {'\0',}; @@ -128,15 +133,24 @@ static int _connect_socket_fd(int fd) addr_un.sun_family = AF_UNIX; strncpy(addr_un.sun_path, FOCUS_SERVER_SOCK, sizeof(addr_un.sun_path)); - if (connect(fd, (struct sockaddr *)&addr_un, sizeof(addr_un)) < 0) { + do { + ret = connect(fd, (struct sockaddr *)&addr_un, sizeof(addr_un)); + if (ret == 0) { + debug_log("connected successfully, fd[%d]", fd); + return MM_ERROR_NONE; + } + strerror_r(errno, str_error, sizeof(str_error)); - debug_error("failed to connect() to %s, err: %s", addr_un.sun_path, str_error); - return MM_ERROR_SOUND_INTERNAL; - } + debug_error("[%2d] failed to connect() to %s, err: %s", + retry_remaining, addr_un.sun_path, str_error); - debug_log("connected successfully, fd[%d]", fd); + usleep(RETRY_CONNECT_INTERVAL_US); + } while (--retry_remaining > 0); - return MM_ERROR_NONE; + debug_error("Timed-out(%u us) for connection", + MAX_CONNECT_RETRY * RETRY_CONNECT_INTERVAL_US); + + return MM_ERROR_SOUND_INTERNAL; } static int _send_data_to_server(int fd, _mm_sound_focus_socket_param_t *data, _mm_sound_focus_socket_result_t *result) diff --git a/packaging/libmm-sound.spec b/packaging/libmm-sound.spec index 0420af2..45bc369 100644 --- a/packaging/libmm-sound.spec +++ b/packaging/libmm-sound.spec @@ -1,6 +1,6 @@ Name: libmm-sound Summary: MMSound Package contains client lib and focus server binary -Version: 0.13.22 +Version: 0.13.23 Release: 0 Group: System/Libraries License: Apache-2.0 -- cgit v1.2.3