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;
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))
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',};
_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));
}
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);
}
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;
}
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;
}
}
- debug_log("focus server socket binding success");
+ debug_msg("focus server socket binding success");
- *fd = socket_fd;
+ *sockfd = socket_fd;
debug_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;
}
#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); \
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',};
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)