diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | include/muse_core_private.h | 3 | ||||
-rw-r--r-- | include/muse_core_watchdog.h | 51 | ||||
-rw-r--r-- | packaging/mused.spec | 10 | ||||
-rw-r--r-- | src/muse_core.c | 76 | ||||
-rw-r--r-- | src/muse_core_ipc.c | 2 | ||||
-rw-r--r-- | src/muse_core_watchdog.c | 140 |
7 files changed, 251 insertions, 32 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 242358b..6aee46e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ SET(SRCS src/muse_core_signal.c src/muse_core_system.c src/muse_core_tool.c + src/muse_core_watchdog.c src/muse_core_workqueue.c ) SET(SRC-SERVER diff --git a/include/muse_core_private.h b/include/muse_core_private.h index e10509d..a2de6fc 100644 --- a/include/muse_core_private.h +++ b/include/muse_core_private.h @@ -27,6 +27,7 @@ #include <gmodule.h> #include "muse_core_module.h" #include "muse_core_ipc.h" +#include "muse_core_watchdog.h" #ifdef __cplusplus extern "C" { #endif @@ -78,9 +79,9 @@ typedef struct muse_core { int stop; int retval; gint running; + muse_core_watchdog_t *watchdog; } muse_core_t; -gpointer muse_core_main_loop(gpointer data); muse_core_t *muse_core_new(void); gboolean muse_core_is_log_enabled(void); diff --git a/include/muse_core_watchdog.h b/include/muse_core_watchdog.h new file mode 100644 index 0000000..bd927ef --- /dev/null +++ b/include/muse_core_watchdog.h @@ -0,0 +1,51 @@ +/* + * muse-core + * + * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: YoungHun Kim <yh8004.kim@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 __MUSE_CORE_WATCHDOG_H__ +#define __MUSE_CORE_WATCHDOG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "muse_core_internal.h" + +#define MUSE_CORE_WATCHDOG_CHECK_PERIOD 10 +#define MUSE_CORE_WATCHDOG_CHECK_COUNT 3 +#define MUSE_CORE_WATCHDOG_TIMER_PERIOD 5 + +typedef struct muse_core_watchdog { + GMutex lock; + GCond cond; + gboolean run; + GThread *thread; + guint timer_id; +} muse_core_watchdog_t; + +int muse_core_watchdog_init(muse_core_watchdog_t *watchdog); +int muse_core_watchdog_deinit(muse_core_watchdog_t *watchdog); +gboolean muse_core_watchdog_attach(muse_core_watchdog_t *watchdog); +int muse_core_watchdog_detach(muse_core_watchdog_t *watchdog); + +#ifdef __cplusplus +} +#endif +#endif /*__MUSE_CORE_WATCHDOG_H__*/ diff --git a/packaging/mused.spec b/packaging/mused.spec index 3e7dadb..8c443c0 100644 --- a/packaging/mused.spec +++ b/packaging/mused.spec @@ -1,6 +1,6 @@ Name: mused Summary: A Multimedia Daemon in Tizen Native API -Version: 0.1.59 +Version: 0.1.61 Release: 0 Group: System/Libraries License: Apache-2.0 @@ -78,10 +78,6 @@ make %{?jobs:-j%jobs} %install rm -rf %{buildroot} -mkdir -p %{buildroot}/usr/share/license -cp LICENSE.APLv2 %{buildroot}/usr/share/license/%{name} -mkdir -p %{buildroot}/usr/bin -cp muse-server %{buildroot}/usr/bin %make_install @@ -130,7 +126,7 @@ chsmack -a "System::Shared" /var/log/%{name} %files %manifest mused.manifest %{_libdir}/libmused.so.* -%{_datadir}/license/%{name} +%license LICENSE.APLv2 %{_unitdir}/muse-server.service %if ("%{VD_PRODUCT_TYPE}" == "AUDIO") %{_unitdir}/starter.target.wants/muse-server.service @@ -149,7 +145,7 @@ chsmack -a "System::Shared" /var/log/%{name} %endif %{TZ_SYS_DATA}/%{name} /var/log/%{name} -/usr/bin/* +%{_bindir}/* %files devel diff --git a/src/muse_core.c b/src/muse_core.c index 3dfc2b7..9795a1b 100644 --- a/src/muse_core.c +++ b/src/muse_core.c @@ -27,6 +27,7 @@ #include "muse_core_log.h" #include "muse_core_module.h" #include "muse_core_msg_json.h" +#include "muse_core_watchdog.h" #include "muse_core_workqueue.h" #include "muse_core_security.h" #include "muse_core_system.h" @@ -41,8 +42,11 @@ #define MUSE_LWIPC_WAIT_TIME 1000 #endif +#define MUSE_CORE_WATCHDOG_CHECK_PERIOD 10 +#define MUSE_CORE_WATCHDOG_CHECK_COUNT 3 +#define MUSE_CORE_WATCHDOG_TIMER_PERIOD 5 + static GMainLoop *g_loop; -static GThread *g_thread; static GMutex g_mutex; static GHashTable *g_table; static int g_table_id; @@ -63,6 +67,7 @@ static gboolean _muse_core_connection_handler(GIOChannel *source, GIOCondition c static int _muse_core_client_new(muse_core_channel_e channel); static void _muse_core_client_table_new(void); static gpointer _muse_core_client_get_fd_ptr(int sock_fd); +static void _muse_core_write_info(char *cmd); static int _muse_core_set_nonblocking(int fd, bool value) { @@ -170,12 +175,16 @@ static muse_core_t *_muse_core_create_new_server_from_fd(int fd[], int type) for (i = 0; i < MUSE_CHANNEL_MAX; i++) { if (!_muse_core_attach_server(fd[i], _muse_core_connection_handler, (gpointer)(intptr_t) i)) { - LOGD("Fail to attach server fd %d", fd[i]); + LOGE("Fail to attach server fd %d", fd[i]); muse_core_respawn(SIGTERM); return NULL; } } + server->watchdog = (muse_core_watchdog_t *) malloc(sizeof(muse_core_watchdog_t)); + if (muse_core_watchdog_init(server->watchdog) != MM_ERROR_NONE) + LOGE("Fail to initialize server watchdog"); + LOGD("Leave"); return server; } @@ -188,6 +197,11 @@ static int _muse_core_free(muse_core_t *server) g_return_val_if_fail(server, retval); + if (muse_core_watchdog_deinit(server->watchdog) == MM_ERROR_NONE) + server->watchdog = NULL; + else + LOGE("Fail to deinitialize server watchdog"); + retval = server->retval; close(server->fd); if (server->data_fd > 0) @@ -196,7 +210,10 @@ static int _muse_core_free(muse_core_t *server) remove(UDS_files[i]); remove(muse_core_config_get_instance()->lockfile); remove(MUSE_DEFAULT_PIDFILE); - MUSE_FREE(server); + + free(server); + server = NULL; + muse_core_workqueue_get_instance()->shutdown(); muse_core_config_get_instance()->free(); muse_core_module_get_instance()->free(); @@ -402,9 +419,22 @@ static gpointer _muse_core_client_get_fd_ptr(int sock_fd) return g_hash_table_lookup(g_table, GINT_TO_POINTER(sock_fd)); } -gpointer muse_core_main_loop(gpointer data) +static void _muse_core_write_info(char *cmd) { - return NULL; + FILE *fp; + char buf[MUSE_MAX_MSG_LEN]; + + g_return_if_fail(cmd); + + fp = popen(cmd, "r"); + + if (fp) { + while (fgets(buf, MUSE_MAX_MSG_LEN, fp)) + LOGW("%s", buf); + + if (pclose(fp) == -1) + LOGE("Fail to pclose"); + } } muse_core_t *muse_core_new() @@ -441,7 +471,7 @@ int muse_core_run() int ready_fd; #endif - LOGI("Enter"); + LOGW("Enter"); g_return_val_if_fail(_muse_core_run() == MM_ERROR_NONE, MUSE_ERR); @@ -455,8 +485,6 @@ int muse_core_run() g_loop = g_main_loop_new(NULL, FALSE); #endif - g_thread = g_thread_new("muse_core_thread", muse_core_main_loop, g_loop); - server = muse_core_new(); if (!server) { g_main_loop_unref(g_loop); @@ -491,10 +519,19 @@ int muse_core_run() LOGE("Fail to subscribe external storage state change"); #endif - LOGD("g_main_loop_run"); - g_main_loop_run(g_loop); + if (muse_core_watchdog_attach(server->watchdog)) { + LOGW("g_main_loop_run"); + + g_main_loop_run(g_loop); + + muse_core_watchdog_detach(server->watchdog); + } else { + LOGE("watchdog thread failed"); + muse_core_log_process_info((int)muse_core_ipc_get_instance()->pid); + } + + LOGW("Leave"); - LOGD("Leave"); return _muse_core_free(server); } @@ -686,24 +723,15 @@ bool muse_core_check_msg_complete(char *msg) return (strlen(ptr) == strlen(END_DELIM_STR)); } -/* There is same function at muse log but we can use this function when muse log is disabled */ void muse_core_log_process_info(int pid) { - FILE *fp; char cmd[MUSE_MAX_MSG_LEN]; - char buf[MUSE_MAX_MSG_LEN]; - - snprintf(cmd, sizeof(cmd), "ps -Lo pcpu,pmem,tid,comm -p %d", (int)pid); - fp = popen(cmd, "r"); + snprintf(cmd, sizeof(cmd), "cat /proc/%d/status | grep Threads", pid); + _muse_core_write_info(cmd); - if (fp) { - while (fgets(buf, MUSE_MAX_MSG_LEN, fp)) - LOGD("%s", buf); - - if (pclose(fp) == -1) - LOGE("Fail to pclose"); - } + snprintf(cmd, sizeof(cmd), "ps -Lo pcpu,pmem,tid,comm -p %d", pid); + _muse_core_write_info(cmd); } void *muse_core_msg_object_new(char *str, int *parse_len, void *err) diff --git a/src/muse_core_ipc.c b/src/muse_core_ipc.c index ff5b12d..a3fd8ea 100644 --- a/src/muse_core_ipc.c +++ b/src/muse_core_ipc.c @@ -154,6 +154,7 @@ static gpointer _muse_core_ipc_dispatch_worker(gpointer data) g_mutex_lock(&g_muse_core_ipc->g_muse_ipc_dispatch_lock); if (muse_core_msg_json_object_get_value(MUSE_MODULE, jobj, &api_module, MUSE_TYPE_INT)) { module->api_module = api_module; + LOGW("api module : %d", module->api_module); if (muse_core_msg_json_object_get_value(PID, jobj, &pid, MUSE_TYPE_INT)) module->pid = pid; module->is_create_api_called = true; @@ -589,6 +590,7 @@ gboolean muse_core_ipc_job_function(muse_core_workqueue_job_t *job) LOGE("thread creation failed : %s", error->message); g_error_free(error); g_hash_table_foreach(g_muse_core_ipc->pid_table, _muse_core_ipc_foreach_get_pid_count, NULL); + muse_core_log_process_info((int)g_muse_core_ipc->pid); module->ch[MUSE_CHANNEL_MSG].dll_handle = muse_core_module_get_instance()->load(API_CREATE); muse_core_cmd_dispatch(module, MUSE_MODULE_COMMAND_RESOURCE_NOT_AVAILABLE); } diff --git a/src/muse_core_watchdog.c b/src/muse_core_watchdog.c new file mode 100644 index 0000000..93e1e6c --- /dev/null +++ b/src/muse_core_watchdog.c @@ -0,0 +1,140 @@ +/* + * muse-core + * + * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: YoungHun Kim <yh8004.kim@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. + * + */ + +#include "muse_core.h" +#include "muse_core_watchdog.h" + +static gboolean _muse_core_watchdog_timer_cb(gpointer data); +static gpointer _muse_core_watchdog_thread(gpointer data); + +static gboolean _muse_core_watchdog_timer_cb(gpointer data) +{ + muse_core_watchdog_t *watchdog = (muse_core_watchdog_t *)data; + + g_return_val_if_fail(watchdog, FALSE); + + g_mutex_lock(&watchdog->lock); + g_cond_signal(&watchdog->cond); + g_mutex_unlock(&watchdog->lock); + + return TRUE; +} + +static gpointer _muse_core_watchdog_thread(gpointer data) +{ + muse_core_watchdog_t *watchdog = (muse_core_watchdog_t *)data; + gint64 end_time = 0; + guint try_count = 0; + + g_return_val_if_fail(watchdog, NULL); + + LOGW("watchdog start : %p", watchdog); + + g_mutex_lock(&watchdog->lock); + + while (watchdog->run) { + end_time = g_get_monotonic_time() + G_TIME_SPAN_SECOND * MUSE_CORE_WATCHDOG_CHECK_PERIOD; + if (g_cond_wait_until(&watchdog->cond, &watchdog->lock, end_time)) { + try_count = 0; + } else { + try_count++; + LOGW("[%d / %d] timeout", try_count, MUSE_CORE_WATCHDOG_CHECK_COUNT); + } + + if (try_count >= MUSE_CORE_WATCHDOG_CHECK_COUNT) { + LOGE("NO RESPONSE FOR MAINLOOP"); + muse_core_respawn(SIGABRT); + } + } + + g_mutex_unlock(&watchdog->lock); + + LOGW("Leave"); + + return NULL; +} + +int muse_core_watchdog_init(muse_core_watchdog_t *watchdog) +{ + g_return_val_if_fail(watchdog, MM_ERROR_INVALID_ARGUMENT); + + g_mutex_init(&watchdog->lock); + g_cond_init(&watchdog->cond); + watchdog->run = TRUE; + + return MM_ERROR_NONE; +} + +int muse_core_watchdog_deinit(muse_core_watchdog_t *watchdog) +{ + g_return_val_if_fail(watchdog, MM_ERROR_INVALID_ARGUMENT); + + g_mutex_clear(&watchdog->lock); + g_cond_clear(&watchdog->cond); + + return MM_ERROR_NONE; +} + +gboolean muse_core_watchdog_attach(muse_core_watchdog_t *watchdog) +{ + g_return_val_if_fail(watchdog, FALSE); + + watchdog->thread = g_thread_try_new("muse_core_watchdog", + _muse_core_watchdog_thread, + (gpointer)watchdog, + NULL); + if (watchdog->thread) { + watchdog->timer_id = g_timeout_add_seconds(MUSE_CORE_WATCHDOG_TIMER_PERIOD, + _muse_core_watchdog_timer_cb, + (gpointer)watchdog); + return TRUE; + } + + return FALSE; +} + +int muse_core_watchdog_detach(muse_core_watchdog_t *watchdog) +{ + gboolean rm_success = FALSE; + + g_return_val_if_fail(watchdog, MM_ERROR_INVALID_ARGUMENT); + + g_mutex_lock(&watchdog->lock); + watchdog->run = FALSE; + g_cond_signal(&watchdog->cond); + g_mutex_unlock(&watchdog->lock); + + LOGW("join watchdog thread - start"); + + g_thread_join(watchdog->thread); + watchdog->thread = NULL; + + LOGW("join watchdog thread - done"); + + rm_success = g_source_remove(watchdog->timer_id); + if (!rm_success) { + LOGE("Failed to remove %d", watchdog->timer_id); + return MM_ERROR_UNKNOWN; + } + + return MM_ERROR_NONE; +} + |