4 * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: YoungHun Kim <yh8004.kim@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 #include "muse_server_private.h"
24 #include <sys/syscall.h>
28 #if !GLIB_CHECK_VERSION(2, 58, 0)
29 #define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void)) (f))
32 #ifdef MUSE_REGISTER_VIP
33 #include <proc_stat.h>
38 #define MUSE_LWIPC_WAIT_TIME 1000
42 static const char *channel_name[MUSE_CHANNEL_MAX] = {
47 static const char *UDS_files[MUSE_CHANNEL_MAX] = {MUSE_SOCK_FILE0, MUSE_SOCK_FILE1};
49 static muse_server_h muse_server;
51 static const char *module_cmd[MUSE_MODULE_COMMAND_MAX] = {
56 "resource_not_available",
57 "external_storage_state_changed",
59 "resource_manager_shutdown"
62 static bool _ms_attach(int fd, muse_module_callback connection_handler, gpointer module_idx);
63 static void _ms_create_new_server_from_fd(int fd[], int type);
64 static int _ms_new(muse_channel_e channel);
65 static int _ms_get_pid(int fd);
66 static void _ms_get_module_addr(int fd, intptr_t *module_addr);
67 static void _ms_check_idle_state(void);
68 static void _ms_check_connection_event(void);
69 static gpointer _ms_diag_check_idle_state_thread(gpointer data);
70 static gpointer _ms_diag_check_connection_event_thread(gpointer data);
71 static void _ms_lock_state(void);
72 static void _ms_unlock_state(void);
73 static gboolean _ms_connection_handler(GIOChannel *source, GIOCondition condition, gpointer data);
75 static void _ms_wait_event(void);
76 static gboolean _ms_idle_cb(gpointer user_data);
78 static void _ms_wait_event(void)
80 const char *lw_event_list[] = { "/run/.wm_ready", "/tmp/avoc_ready" };
81 unsigned int count = sizeof(lw_event_list) / sizeof(char *);
83 if (LwipcWaitMultiEvents(lw_event_list, count, true, MUSE_LWIPC_WAIT_TIME, NULL, 0) != 0)
84 LOGE("Fail to receive Multiple Events");
88 static bool _ms_attach(int fd, muse_module_callback connection_handler, gpointer module_idx)
90 GIOChannel *channel = NULL;
95 muse_return_val_if_fail(muse_server, false);
96 muse_return_val_if_fail(muse_core_fd_is_valid(fd), false);
98 channel = g_io_channel_unix_new(fd);
99 muse_return_val_if_fail(channel, false);
101 src = g_io_create_watch(channel, G_IO_IN);
103 LOGE("g_io_create_watch() is failed");
104 g_io_channel_unref(channel);
108 g_source_set_callback(src, G_SOURCE_FUNC(connection_handler), module_idx, NULL);
110 if (g_source_attach(src, g_main_loop_get_context(muse_server->main_loop)) == 0) {
111 LOGE("g_source_attach() is failed");
112 g_io_channel_unref(channel);
118 g_io_channel_unref(channel);
125 static void _ms_create_new_server_from_fd(int fd[], int type)
128 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
132 muse_return_if_fail(muse_server);
134 muse_server->msg_fd = fd[MUSE_CHANNEL_MSG];
135 muse_server->data_fd = fd[MUSE_CHANNEL_DATA];
136 muse_server->type = type;
138 gettimeofday(&muse_server->tv_s, NULL);
140 for (i = 0; i < MUSE_CHANNEL_MAX; i++) {
141 if (!_ms_attach(fd[i], _ms_connection_handler, (gpointer)(intptr_t) i)) {
142 snprintf(err_msg, sizeof(err_msg), "Fail to attach server fd %d", fd[i]);
153 static int _ms_new(muse_channel_e channel)
156 struct sockaddr_un addr_un;
157 socklen_t address_len;
158 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
160 muse_return_val_if_fail(channel < MUSE_CHANNEL_MAX, MM_ERROR_INVALID_ARGUMENT);
162 unlink(UDS_files[channel]);
165 fd = socket(AF_UNIX, SOCK_STREAM, 0); /* Unix Domain Socket */
166 if (!muse_core_fd_is_valid(fd)) {
167 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
168 LOGE("socket failed sock (%d) : %s", errno, err_msg);
172 LOGD("muse server fd : %d", fd);
174 memset(&addr_un, 0, sizeof(addr_un));
175 addr_un.sun_family = AF_UNIX;
176 strncpy(addr_un.sun_path, UDS_files[channel], sizeof(addr_un.sun_path) - 1);
177 address_len = sizeof(addr_un);
179 /* Bind to filename */
180 if (bind(fd, (struct sockaddr *)&addr_un, address_len) < 0) {
182 strerror_r(errsv, err_msg, MUSE_MSG_LEN_MAX);
183 LOGE("[%d] socket bind failed (%d) %s", fd, errsv, err_msg);
184 muse_core_log_file_list(UDS_files[channel]);
185 ms_log_user_group_info();
186 if (errsv == EADDRINUSE)
187 unlink(addr_un.sun_path);
192 /* Setup listen queue */
193 if (listen(fd, 5) == MUSE_ERR) {
194 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
195 LOGE("[%d] listen failed (%d) %s", fd, errno, err_msg);
196 muse_core_log_file_list(UDS_files[channel]);
197 ms_log_user_group_info();
202 if (muse_core_set_nonblocking(fd, false) < 0) /* blocking */
203 LOGE("failed to set server socket to blocking");
208 static int _ms_get_pid(int fd)
210 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
211 struct ucred credentials;
214 length = sizeof(struct ucred);
215 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &credentials, &length) < 0) {
216 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
217 LOGE("failed to get the value of credential type %s", err_msg);
221 muse_core_update_fd_state(fd);
223 return credentials.pid;
226 static void _ms_get_module_addr(int fd, intptr_t *module_addr)
231 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
232 char recv_buf[MUSE_MSG_LEN_MAX] = {'\0',};
235 if (muse_core_msg_recv_fd(fd, recv_buf, MUSE_MSG_LEN_MAX, NULL) <= 0) {
236 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
237 LOGE("failed to receive message for module %s", err_msg);
241 jobj = muse_core_msg_object_new(recv_buf, NULL, NULL);
243 ret = muse_core_msg_object_get_value(MSG_KEY_MODULE_ADDR, jobj, MUSE_TYPE_POINTER, module_addr);
244 muse_core_msg_object_free(jobj);
246 LOGE("[%d] Error - module_addr %s", try_count, recv_buf);
250 } while (++try_count < MS_RECV_TRY_COUNT_MAX);
253 static gboolean _ms_connection_handler(GIOChannel *source, GIOCondition condition, gpointer data)
255 int server_sockfd, client_sockfd, pid, idx, len;
256 socklen_t client_len;
257 struct sockaddr_un client_address;
258 muse_channel_e channel = (muse_channel_e)data;
259 muse_module_h m = NULL;
260 muse_module_h peeked_m = NULL;
261 muse_module_h candidate_m = NULL;
262 intptr_t module_addr = 0;
263 GQueue *instance_queue = NULL;
264 ms_connection_t *connection = NULL;
268 muse_return_val_if_fail(muse_server, FALSE);
270 connection = muse_server->connection;
271 muse_return_val_if_fail(connection, FALSE);
275 if (!ms_is_server_ready()) {
276 LOGW("Now mused state is not ready...");
282 server_sockfd = g_io_channel_unix_get_fd(source);
283 if (!muse_core_fd_is_valid(server_sockfd)) {
284 LOGE("Critical Error : server %d is invalid", server_sockfd);
286 muse_core_dump_fd_state(server_sockfd);
291 client_len = sizeof(client_address);
293 LOGI("[%d] Try to accept...", server_sockfd);
294 client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);
295 if (!muse_core_fd_is_valid(client_sockfd)) {
296 LOGE("Critical Error : accept %d is invalid", client_sockfd);
297 muse_core_dump_fd_state(client_sockfd);
298 close(server_sockfd);
304 LOGI("server : %d client [%s channel] : %d", server_sockfd, channel_name[channel], client_sockfd);
306 pid = _ms_get_pid(client_sockfd);
308 if (channel == MUSE_CHANNEL_MSG) {
309 m = g_new0(muse_module_t, 1);
310 m->ch[MUSE_CHANNEL_MSG].sock_fd = client_sockfd;
312 g_mutex_init(&m->dispatch_lock);
314 ms_ipc_create_msg_dispatch_worker(m);
317 _ms_get_module_addr(client_sockfd, &module_addr);
319 ms_connection_lock(connection);
321 instance_queue = connection->instance_queue;
322 len = g_queue_get_length(instance_queue);
324 m = (muse_module_h)module_addr;
326 for (idx = 0; idx < len; idx++) {
327 peeked_m = (muse_module_h)g_queue_peek_nth(instance_queue, idx);
329 LOGW("[%d] Make sure if the queue length is changed (%d = %d), which means that it was destroyed somewhere",
330 idx, len, g_queue_get_length(instance_queue));
334 if (peeked_m->pid != pid)
339 LOGE("muse-server can't support the error case which there are several modules now");
340 ms_connection_unlock(connection);
344 if (!muse_core_fd_is_valid(peeked_m->ch[MUSE_CHANNEL_DATA].sock_fd))
345 candidate_m = peeked_m;
347 SECURE_LOGW("already paired module %p", peeked_m);
355 if (muse_core_fd_is_valid(m->ch[MUSE_CHANNEL_DATA].sock_fd)) {
356 SECURE_LOGE("[%d] %s pid %d %p you had better check if instance destroy completed properly",
357 client_sockfd, ms_config_get_host_name(m->idx), pid, m);
358 ms_connection_unlock(connection);
362 m->ch[MUSE_CHANNEL_DATA].sock_fd = client_sockfd;
363 SECURE_LOGI("%s (pid %d) module : %p module addr from client : %p",
364 ms_config_get_host_name(m->idx), pid, m, (void *)module_addr);
370 m->ch[MUSE_CHANNEL_DATA].sock_fd = client_sockfd;
371 SECURE_LOGW("[%d] %s pid %d %p restore module address at the only one null data channel",
372 client_sockfd, ms_config_get_host_name(m->idx), pid, m);
375 ms_connection_unlock(connection);
377 ms_ipc_create_data_dispatch_worker(m);
386 close(server_sockfd);
387 close(client_sockfd);
390 if (channel == MUSE_CHANNEL_MSG)
393 muse_core_connection_close(m->ch[MUSE_CHANNEL_MSG].sock_fd);
404 static void _ms_check_idle_state(void)
406 ms_connection_t *connection = NULL;
407 ms_config_t *conf = NULL;
408 struct timeval tv_c, tv_r;
409 int instance_number, timeout;
410 static int period_idx = 1;
412 muse_return_if_fail(muse_server);
413 muse_return_if_fail(muse_server->state == MUSE_SERVER_STATE_READY);
415 connection = muse_server->connection;
416 muse_return_if_fail(connection);
418 conf = muse_server->conf;
419 muse_return_if_fail(conf);
421 gettimeofday(&tv_c, NULL);
422 timersub(&tv_c, &muse_server->tv_s, &tv_r);
424 timeout = (int)tv_r.tv_sec;
426 ms_connection_lock(connection);
428 instance_number = g_queue_get_length(connection->instance_queue);
430 if (timeout >= ms_config_get_log_period() * period_idx) {
431 LOGW("total number of modules = %d ( %s)", instance_number, muse_server->instance_pid_info);
435 ms_connection_unlock(connection);
437 if (conf->is_on_demand) {
438 if (instance_number == 0 && timeout >= ms_config_get_max_idle_time()) {
439 LOGE("Timeout exit !!! [Idle time] %d sec", timeout);
440 ms_remove_ready_file();
446 static void _ms_check_connection_event(void)
448 ms_connection_state_e state = MUSE_CONNECTION_STATE_INVALID;
451 muse_return_if_fail(muse_server);
453 if (ms_connection_get_state(&state, &fd)) {
454 gettimeofday(&muse_server->tv_s, NULL);
455 if (state == MUSE_CONNECTION_STATE_CONNECTED) {
456 /* will be updated about connection at the next patch */
457 } else if (state == MUSE_CONNECTION_STATE_DISCONNECTED) {
458 LOGD("Diagnostic thread checks the memory of idle");
459 ms_check_cpu_memory(fd);
464 static gpointer _ms_diag_check_idle_state_thread(gpointer data)
466 int idle_state_wait_time = ms_config_get_idle_state_wait_time();
468 muse_return_val_if_fail(muse_server, NULL);
469 muse_return_val_if_fail(idle_state_wait_time > 0, NULL);
471 while (ms_is_server_ready()) {
472 _ms_check_idle_state();
473 sleep(idle_state_wait_time);
479 static gpointer _ms_diag_check_connection_event_thread(gpointer data)
481 muse_return_val_if_fail(muse_server, NULL);
483 while (ms_is_server_ready())
484 _ms_check_connection_event();
489 static void _ms_lock_state(void)
491 muse_return_if_fail(muse_server);
492 g_mutex_lock(&muse_server->state_lock);
495 static void _ms_unlock_state(void)
497 muse_return_if_fail(muse_server);
498 g_mutex_unlock(&muse_server->state_lock);
501 static gboolean _ms_idle_cb(gpointer user_data)
503 if (!ms_create_ready_file())
504 LOGE("%s file creation is failed", MUSE_SERVER_READY);
506 ms_diag_thread_create();
508 return G_SOURCE_REMOVE;
511 static void _ms_init(void)
517 muse_server->system = g_new0(ms_system_t, 1);
518 ms_system_init(muse_server->system);
520 muse_server->conf = g_new0(ms_config_t, 1);
521 ms_config_init(muse_server->conf);
523 muse_server->log = g_new0(ms_log_t, 1);
524 ms_log_init(muse_server->log);
526 muse_server->security = g_new0(ms_security_t, 1);
527 ms_security_init(muse_server->security);
529 for (idx = 0; idx < muse_server->conf->host_cnt; idx++) {
530 muse_server->module[idx] = g_new0(ms_module_t, 1);
531 muse_server->module[idx]->idx = idx;
532 ms_module_init(muse_server->module[idx]);
535 #ifdef MUSE_USE_WATCHDOG
536 muse_server->watchdog = g_new0(ms_watchdog_t, 1);
537 if (ms_watchdog_init(muse_server->watchdog) != MM_ERROR_NONE)
538 LOGE("Fail to initialize server watchdog");
541 muse_server->connection = g_new0(ms_connection_t, 1);
542 ms_connection_init(muse_server->connection);
546 g_mutex_init(&muse_server->state_lock);
548 muse_core_create_fd_table();
550 muse_server->cpu_threshold = ms_config_get_cpu_threshold();
552 muse_server->main_loop = g_main_loop_new(NULL, FALSE);
553 muse_return_if_fail(muse_server->main_loop);
558 int ms_open_lockfile(void)
560 int fd, already_running;
561 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
562 char *lockfile = NULL;
564 muse_return_val_if_fail(muse_server, MUSE_ERR);
566 lockfile = ms_config_get_lockfile();
567 muse_return_val_if_fail(lockfile, MUSE_ERR);
569 muse_core_remove_symlink((const char *)lockfile);
570 fd = open(lockfile, O_RDONLY);
571 if (fd == -1 && errno != ENOENT) {
572 /* Cannot open file even though file exists. */
573 snprintf(err_msg, sizeof(err_msg), "Cannot open lock file %s", lockfile);
574 LOGE("open failed : %s", err_msg);
576 } else if (fd != -1) {
577 already_running = flock(fd, LOCK_EX | LOCK_NB) == -1;
579 if (already_running) {
580 LOGE("File already locked. There's already a server running");
585 /* Lock file does not exist, or is not locked. Create a new lockfile and lock it. */
586 fd = open(lockfile, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
588 LOGE("dataserver: Cannot create lock file");
592 if (flock(fd, LOCK_EX | LOCK_NB) != 0) {
593 LOGE("Can't lock the lock file \"%s\". " "Is another instance running?", lockfile);
600 return MM_ERROR_NONE;
603 void ms_diag_thread_create(void)
605 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
606 GError *error = NULL;
608 muse_return_if_fail(muse_server);
610 muse_server->diag_idle_state_thread = g_thread_try_new("diag_idle_state",
611 _ms_diag_check_idle_state_thread, muse_server->main_loop, &error);
612 if (!muse_server->diag_idle_state_thread && error) {
613 snprintf(err_msg, sizeof(err_msg), "diag_idle_state_thread creation failed : %s", error->message);
616 ms_log_process_info(muse_server->pid);
619 muse_server->diag_connection_event_thread = g_thread_try_new("diag_connection_event",
620 _ms_diag_check_connection_event_thread, muse_server->main_loop, &error);
621 if (!muse_server->diag_connection_event_thread && error) {
622 snprintf(err_msg, sizeof(err_msg), "diag_connection_event_thread creation failed : %s", error->message);
625 ms_log_process_info(muse_server->pid);
629 void ms_diag_thread_destroy(void)
631 muse_return_if_fail(muse_server);
635 if (muse_server->diag_idle_state_thread) {
636 g_thread_join(muse_server->diag_idle_state_thread);
637 muse_server->diag_idle_state_thread = NULL;
640 if (muse_server->diag_connection_event_thread) {
641 g_thread_join(muse_server->diag_connection_event_thread);
642 muse_server->diag_connection_event_thread = NULL;
648 void ms_setup_syslog(void)
650 int flags = LOG_CONS|LOG_NDELAY|LOG_PID;
651 if (isatty(STDOUT_FILENO))
654 openlog("mused", flags, LOG_DAEMON);
655 LOGD("openlog - mused");
658 void ms_fork(int *notify_fd)
662 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
663 char msg[MUSE_MSG_LEN_MAX] = {'\0',};
665 if (pipe(fds) == MUSE_ERR) {
666 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
667 LOGE("Failed to create pipe to get child status: %s", err_msg);
671 if ((pid = fork()) < 0) {
672 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
673 LOGE("Error: fork() failed: %s", err_msg);
675 } else if (pid != 0) {
677 /* Read in a string from the pipe */
678 if (read(fds[0], msg, sizeof(msg)) <= 0) {
679 LOGE("Failed to read from a file descriptor [%d]", fds[0]);
685 /* Parent process closes up output side of pipe */
686 if (!strcmp(msg, MSG_DONE)) {
687 LOGI("Successfully daemonized");
690 LOGE("Daemonizing failed after fork");
693 } else if (pid == 0) {
694 /* Child process closes up input side of pipe */
700 pid_t ms_daemonize(int *notify_fd)
705 muse_return_val_if_fail(notify_fd, MUSE_ERR);
709 if ((pid = setsid()) < 0) {
710 LOGE("create new session");
714 /* change the file mode mask */
718 LOGD("result = %d sid: %d pgid: %d pid: %d ppid: %d", result, (int)getsid(0), (int)getpgid(0), (int)pid, (int)getppid());
720 /* redirect fds to /dev/null */
721 fd = open("/dev/null", O_RDWR);
722 if (!muse_core_fd_is_valid(fd)) {
723 LOGE("Critical Error : %d is invalid", fd);
728 close(STDOUT_FILENO);
729 close(STDERR_FILENO);
731 dup2(fd, STDIN_FILENO);
732 dup2(fd, STDOUT_FILENO);
733 dup2(fd, STDERR_FILENO);
740 void ms_daemonize_complete(int notify_fd)
744 muse_return_if_fail(muse_core_fd_is_valid(notify_fd));
746 #ifdef MUSE_REGISTER_VIP
747 proc_stat_set_vip_process();
750 write(notify_fd, MSG_DONE, strlen(MSG_DONE) + 1);
751 LOGI("[%d] Notify parent process that child initialization is done", notify_fd);
757 void ms_gst_init(char **cmd)
762 gboolean ret = FALSE;
765 #ifdef MUSE_TTRACE_LOG
766 trace_begin("MUSE:gst_init");
769 gst_param_cnt = ms_config_get_gst_param_cnt();
772 argv = g_malloc0(sizeof(gchar *) * (gst_param_cnt + 1));
774 argv[argc++] = (gchar *)cmd[0];
775 for (; argc <= gst_param_cnt; argc++) {
776 argv[argc] = ms_config_get_gst_param_str(argc - 1);
777 LOGI("%d %s", argc, argv[argc]);
780 /* initializing gstreamer */
781 ret = gst_init_check(&argc, &argv, &err);
783 LOGE("Could not initialize GStreamer: %s ", err ? err->message : "unknown error occurred");
788 LOGI("gst_init_check is completed");
793 LOGI("complete to initialize gstreamer");
795 #ifdef MUSE_TTRACE_LOG
800 void ms_gst_preload_plugin(void)
803 char *saveptr = NULL;
804 char plugin_path[128];
805 const char *delimeters = " ,";
806 gchar *gst_preload_plugins = g_strdup(ms_config_get_gst_preload_plugins());
807 GstPlugin *plugin = NULL;
809 muse_return_if_fail(gst_preload_plugins);
811 LOGI("preload plugins [%s]", gst_preload_plugins);
813 token = strtok_r(gst_preload_plugins, delimeters, &saveptr);
815 snprintf(plugin_path, sizeof(plugin_path), "%s/gstreamer-1.0/libgst%s.so", LIBDIR, token);
817 LOGI(" plugin path : %s", plugin_path);
819 plugin = gst_plugin_load_file(plugin_path, NULL);
821 gst_object_unref(plugin);
823 LOGW("failed to load plugin [%s]", plugin_path);
825 token = strtok_r(NULL, delimeters, &saveptr);
828 g_free(gst_preload_plugins);
833 int ms_pidfile_create(const char *path, pid_t pid)
837 char pid_buf[MUSE_MSG_LEN] = {'\0',};
838 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
840 muse_return_val_if_fail(path, MM_ERROR_INVALID_ARGUMENT);
841 muse_core_remove_symlink(path);
842 fd = open(path, O_WRONLY | O_CREAT, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
844 if (!muse_core_fd_is_valid(fd)) {
845 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
846 LOGE("Fail to open pidfile [%s] : %s", path, err_msg);
847 return MM_ERROR_FILE_NOT_FOUND;
850 lock.l_type = F_WRLCK;
852 lock.l_whence = SEEK_SET;
855 if (fcntl(fd, F_SETLK, &lock) < 0) {
856 if (errno != EACCES && errno != EAGAIN) {
857 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
858 LOGE("Fail to lock pidfile [%s] : %s", path, err_msg);
860 LOGE("process is already running");
863 return MM_ERROR_FILE_INTERNAL;
866 if (ftruncate(fd, 0) < 0) {
867 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
868 LOGE("Fail to truncate pidfile [%s] : %s", path, err_msg);
870 return MM_ERROR_FILE_INTERNAL;
873 memset(pid_buf, 0, sizeof(pid_buf));
874 snprintf(pid_buf, sizeof(pid_buf), "%u", pid);
876 if (write(fd, pid_buf, strlen(pid_buf)) != (int)strlen(pid_buf)) {
877 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
878 LOGE("Fail to write pid to pidfile [%s] : %s", path, err_msg);
880 return MM_ERROR_FILE_WRITE;
884 return MM_ERROR_NONE;
887 void ms_init(char **argv)
891 muse_module_cmd_dispatchfunc *cmd_dispatcher = NULL;
895 muse_server = g_new0(muse_server_t, 1);
899 muse_server->pid = ms_daemonize(¬ify_fd);
901 if (ms_pidfile_create(MUSE_DEFAULT_PIDFILE, muse_server->pid) != MM_ERROR_NONE)
904 LOGD("MUSE_DEFAULT_PIDFILE(%s) file was created", MUSE_DEFAULT_PIDFILE);
908 muse_return_if_fail(ms_get_instance());
910 muse_return_if_fail(ms_open_lockfile() == MM_ERROR_NONE);
914 ms_daemonize_complete(notify_fd);
916 #ifdef MUSE_TTRACE_LOG
920 ms_system_subscribe_external_event(ms_get_instance()->system);
922 #ifdef MUSE_USE_WATCHDOG
923 if (!ms_watchdog_attach(ms_get_instance()->watchdog)) {
924 LOGE("watchdog thread failed");
925 ms_log_process_info(muse_server->pid);
932 #ifdef MUSE_TTRACE_LOG
933 trace_begin("MUSE:preloading module");
935 for (idx = 0; idx < ms_config_get_host_cnt(); idx++) {
936 if (0 == strncmp(ms_config_get_preloaded_value(idx), "yes", strlen("yes") + 1)) {
937 g_module_symbol(ms_module_open(idx), CMD_DISPATCHER, (gpointer *)&cmd_dispatcher);
938 if (cmd_dispatcher && cmd_dispatcher[MUSE_MODULE_COMMAND_INITIALIZE])
939 cmd_dispatcher[MUSE_MODULE_COMMAND_INITIALIZE](NULL);
942 #ifdef MUSE_TTRACE_LOG
946 #ifdef MUSE_TTRACE_LOG
947 trace_begin("MUSE:preloading GST module");
949 ms_gst_preload_plugin();
950 #ifdef MUSE_TTRACE_LOG
954 #ifdef MUSE_GCOV_TEST
955 muse_core_setenv("GCOV_PREFIX", "/tmp", 1);
961 muse_server_h ms_get_instance(void)
966 gboolean ms_check_module_idx(int idx)
968 int module_cnt = ms_config_get_host_cnt();
970 if (idx < 0 || idx >= module_cnt) {
971 LOGE("%d error - the number of modules is %d", idx, module_cnt);
978 ms_module_t *ms_get_module_instance(int idx)
980 muse_return_val_if_fail(ms_check_module_idx(idx), NULL);
982 return muse_server->module[idx];
987 int retval = MUSE_ERR;
992 muse_return_val_if_fail(muse_server, retval);
993 muse_return_val_if_fail(muse_server->conf, retval);
994 muse_return_val_if_fail(muse_server->connection, retval);
995 muse_return_val_if_fail(muse_server->log, retval);
996 muse_return_val_if_fail(muse_server->security, retval);
997 muse_return_val_if_fail(muse_server->watchdog, retval);
998 muse_return_val_if_fail(muse_server->diag_idle_state_thread, retval);
999 muse_return_val_if_fail(muse_server->diag_connection_event_thread, retval);
1001 ms_recursive_rmdir(MUSE_DATA_ROOT_PATH);
1003 ms_set_state(MUSE_SERVER_STATE_IDLE);
1005 ms_diag_thread_destroy();
1007 #ifdef MUSE_USE_WATCHDOG
1008 ms_watchdog_detach(muse_server->watchdog);
1010 if (ms_watchdog_deinit(muse_server->watchdog) == MM_ERROR_NONE)
1011 free(muse_server->watchdog);
1013 LOGE("Fail to deinitialize server watchdog");
1016 ms_remove_ready_file();
1018 retval = muse_server->retval;
1019 muse_core_fd_close(muse_server->msg_fd);
1020 muse_core_fd_close(muse_server->data_fd);
1021 for (idx = 0; idx < MUSE_CHANNEL_MAX; idx++) {
1022 if (remove(UDS_files[idx]) == MUSE_ERR)
1023 LOGE("remove %s failed", UDS_files[idx]);
1026 if (remove(MUSE_DEFAULT_PIDFILE) == -1)
1027 LOGE("remove %s failed [errno : %d]", MUSE_DEFAULT_PIDFILE, errno);
1029 for (idx = 0; idx < muse_server->conf->host_cnt; idx++)
1030 ms_module_deinit(muse_server->module[idx]);
1032 ms_security_deinit(muse_server->security);
1033 muse_server->security = NULL;
1035 ms_system_deinit(muse_server->system);
1036 muse_server->system = NULL;
1038 ms_log_deinit(muse_server->log);
1039 muse_server->log = NULL;
1041 ms_config_deinit(muse_server->conf);
1042 muse_server->conf = NULL;
1044 ms_connection_deinit(muse_server->connection);
1045 muse_server->connection = NULL;
1047 muse_core_destroy_fd_table();
1051 g_mutex_clear(&muse_server->state_lock);
1053 g_free(muse_server);
1060 void ms_check_cpu_memory(int fd)
1062 int used_pss, memory_threshold, cpu_usage;
1063 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
1064 ms_connection_t *connection = NULL;
1066 muse_return_if_fail(muse_server);
1068 connection = muse_server->connection;
1069 muse_return_if_fail(connection);
1071 ms_connection_lock(connection);
1073 while (muse_core_fd_is_valid(fd)) {
1074 g_cond_wait(&connection->cond, &connection->lock);
1075 LOGI("[%d] is_valid : %d", fd, muse_core_fd_is_valid(fd));
1078 if (g_queue_is_empty(connection->instance_queue) && ms_is_server_ready()) {
1079 used_pss = ms_system_get_memory_usage(muse_server->pid);
1080 cpu_usage = muse_core_get_process_cpu_usage(muse_server->pid);
1082 LOGW("[%d] Proportional set size %d (KByte) (CPU %d)", muse_server->pid, used_pss, cpu_usage);
1083 memory_threshold = ms_config_get_memory_threshold();
1085 if (used_pss >= memory_threshold || cpu_usage >= muse_server->cpu_threshold) {
1086 ms_set_state(MUSE_SERVER_STATE_IDLE);
1087 ms_log_process_info(muse_server->pid);
1089 snprintf(err_msg, sizeof(err_msg), "[Memory Leak] %d >= %d (KByte) [CPU] %d >= %d (percent)",
1090 used_pss, memory_threshold, cpu_usage, muse_server->cpu_threshold);
1092 LOGE("%s", err_msg);
1093 ms_connection_unlock(connection);
1094 ms_respawn(SIGTERM);
1097 muse_core_remove_all_fd_table();
1099 LOGI("skip cpu memory check due to instance queue length : %d", g_queue_get_length(connection->instance_queue));
1102 ms_connection_unlock(connection);
1105 int ms_kill_thread(int signo)
1107 return syscall(__NR_tkill, syscall(__NR_gettid), signo);
1112 int fd[MUSE_CHANNEL_MAX];
1115 for (i = 0; i < MUSE_CHANNEL_MAX; i++) {
1116 if (ms_config_is_on_demand() && i == MUSE_CHANNEL_MSG)
1117 fd[i] = SD_LISTEN_FDS_START;
1121 if (!muse_core_fd_is_valid(fd[i])) {
1122 LOGE("Failed to create socket server %d", i);
1123 for (j = 0; j < i; j++)
1129 _ms_create_new_server_from_fd(fd, READ | PERSIST);
1136 muse_return_if_fail(muse_server->main_loop);
1138 muse_return_if_fail(g_idle_add(_ms_idle_cb, NULL) > 0);
1140 LOGI("g_main_loop_run");
1141 g_main_loop_run(muse_server->main_loop);
1146 void ms_cmd_dispatch(muse_module_h m, muse_module_command_e cmd)
1148 muse_module_cmd_dispatchfunc *cmd_dispatcher = NULL;
1150 if (m->ch[MUSE_CHANNEL_MSG].dll_handle &&
1151 g_module_symbol(m->ch[MUSE_CHANNEL_MSG].dll_handle, CMD_DISPATCHER, (gpointer *)&cmd_dispatcher)) {
1152 if (cmd_dispatcher && cmd_dispatcher[cmd])
1153 cmd_dispatcher[cmd](m);
1157 void ms_respawn(int signo)
1159 pid_t pid = getpid();
1160 LOGE("send %d process signal %d", (int)pid, signo);
1162 muse_return_if_fail(muse_server);
1164 ms_set_state(MUSE_SERVER_STATE_IDLE);
1165 ms_kill_thread(signo);
1168 int ms_get_pid(muse_module_h m)
1170 muse_return_val_if_fail(m, MUSE_ERR);
1174 void ms_log_process_info(int pid)
1176 muse_core_log_process_thread_info(pid);
1178 muse_core_log_process_opened_fds(pid);
1180 muse_core_log_process_cpu_memory(pid);
1183 void ms_log_user_group_info(void)
1187 char buffer[MUSE_MSG_MAX_LENGTH];
1188 struct passwd pwbuf;
1189 struct passwd *pwbufp;
1191 struct group *gbufp;
1196 getpwuid_r(uid, &pwbuf, buffer, sizeof(buffer), &pwbufp);
1197 muse_return_if_fail(pwbufp);
1199 getgrgid_r(gid, &gbuf, buffer, sizeof(buffer), &gbufp);
1200 muse_return_if_fail(gbufp);
1202 LOGE("user [%s : %lu] group [%s : %lu]", pwbufp->pw_name, (unsigned long)uid, gbufp->gr_name, (unsigned long)gid);
1205 gboolean ms_is_log_enabled(void)
1207 return ms_config_is_log_enabled();
1210 gboolean ms_init_bufmgr(void)
1214 muse_return_val_if_fail(muse_server, FALSE);
1216 muse_server->bufmgr = tbm_bufmgr_init(-1);
1217 if (!muse_server->bufmgr) {
1218 LOGE("Error - tbm_bufmgr_init");
1219 ms_log_user_group_info();
1223 LOGD("Leave bufmgr: %p", muse_server->bufmgr);
1228 void ms_deinit_bufmgr(void)
1232 muse_return_if_fail(muse_server);
1233 muse_return_if_fail(muse_server->bufmgr);
1235 tbm_bufmgr_deinit(muse_server->bufmgr);
1240 void ms_cmd_dispatch_foreach_func(gpointer data, gpointer user_data)
1242 muse_module_h m = (muse_module_h)data;
1243 ms_cmd_dispatcher_info_t *dispatch = (ms_cmd_dispatcher_info_t *)user_data;
1244 muse_module_command_e cmd;
1245 muse_external_storage_info_t *storage;
1247 muse_return_if_fail(muse_server);
1248 muse_return_if_fail(m);
1249 muse_return_if_fail(dispatch);
1251 cmd = dispatch->cmd;
1253 if (cmd == MUSE_MODULE_COMMAND_EXTERNAL_STORAGE_STATE_CHANGED) {
1254 storage = &dispatch->storage;
1255 LOGD("external storage id %d state %d path %s", storage->id, storage->state, storage->path);
1256 muse_server_set_user_data(m, (void *)storage);
1259 ms_cmd_dispatch(m, cmd);
1260 SECURE_LOGI("[%s] %p (%s)", module_cmd[cmd], m, muse_server->conf->host[m->idx]);
1262 if (cmd == MUSE_MODULE_COMMAND_EXTERNAL_STORAGE_STATE_CHANGED)
1263 muse_server_set_user_data(m, NULL);
1266 void ms_set_state(ms_state_e state)
1268 muse_return_if_fail(muse_server);
1270 g_mutex_lock(&muse_server->state_lock);
1271 muse_server->state = state;
1272 g_mutex_unlock(&muse_server->state_lock);
1275 gboolean ms_is_server_ready(void)
1277 muse_return_val_if_fail(muse_server, FALSE);
1279 return muse_server->state == MUSE_SERVER_STATE_READY;
1282 gboolean ms_create_ready_file(void)
1285 #ifndef MUSE_USE_LWIPC
1289 #ifdef MUSE_USE_LWIPC
1292 ms_set_state(MUSE_SERVER_STATE_READY);
1294 if (LwipcEventDone(MUSE_SERVER_READY) < 0) {
1295 LOGE("Fail to send server ready done event");
1299 ready_fd = creat(MUSE_SERVER_READY, 0644);
1300 if (muse_core_fd_is_valid(ready_fd)) {
1301 LOGD("MUSE_SERVER_READY(%s) file was created", MUSE_SERVER_READY);
1304 ms_set_state(MUSE_SERVER_STATE_READY);
1306 LOGE("[%d] Fail to create MUSE_SERVER_READY(%s)", ready_fd, MUSE_SERVER_READY);
1316 void ms_remove_ready_file(void)
1318 #ifdef MUSE_USE_LWIPC
1319 (void)LwipcResetEvent(MUSE_SERVER_READY);
1321 (void)unlink(MUSE_SERVER_READY);
1322 (void)unlink(MUSE_DEFAULT_PIDFILE);