summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--include/muse_core_private.h3
-rw-r--r--include/muse_core_watchdog.h51
-rw-r--r--packaging/mused.spec10
-rw-r--r--src/muse_core.c76
-rw-r--r--src/muse_core_ipc.c2
-rw-r--r--src/muse_core_watchdog.c140
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;
+}
+