focus_socket: wait for socket listen ready 43/284543/7 accepted/tizen/unified/20221207.171506
authorSeungbae Shin <seungbae.shin@samsung.com>
Fri, 18 Nov 2022 11:15:09 +0000 (20:15 +0900)
committerSeungbae Shin <seungbae.shin@samsung.com>
Tue, 6 Dec 2022 05:24:42 +0000 (14:24 +0900)
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
focus_server/mm_sound_focus_server.c
focus_server/mm_sound_mgr_focus_socket.c
mm_sound_focus_socket.c
packaging/libmm-sound.spec

index 9768c48..2a0e67d 100644 (file)
@@ -1,9 +1,29 @@
+/*
+ * libmm-sound
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Sangchul Lee <sc11.lee@samsung.com>
+ *
+ * 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__ */
index f6adf8f..3d7a581 100644 (file)
@@ -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();
index a06800d..162c552 100644 (file)
@@ -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 voidready_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;
 }
index 4d8c96f..fa5083c 100644 (file)
@@ -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)
index 0420af2..45bc369 100644 (file)
@@ -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