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"
27 #include <tzplatform_config.h>
29 #if !GLIB_CHECK_VERSION(2, 58, 0)
30 #define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void)) (f))
33 #if defined (__aarch64__) || defined (__x86_64__)
34 #define MUSE_DEFAULT_MMAP_THRESHOLD_MAX (512 * 1024)
38 #ifdef MUSE_VIP_REGISTERED
39 #include <proc_stat.h>
44 #define MUSE_LWIPC_WAIT_TIME 1000
48 static const char *channel_name[MUSE_CHANNEL_MAX] = {
53 static const char *UDS_files[MUSE_CHANNEL_MAX] = {MUSE_MSG_SOCK, MUSE_DATA_SOCK};
55 static muse_server_h muse_server;
57 static const char *module_cmd[MUSE_MODULE_COMMAND_MAX] = {
62 "resource_not_available",
63 "external_storage_state_changed",
65 "resource_manager_shutdown"
68 static bool _ms_attach(int fd, muse_module_callback connection_handler, gpointer module_idx);
69 static void _ms_create_new_server_from_fd(int fd[], int type);
70 static int _ms_new(muse_channel_e channel);
71 static int _ms_get_pid(int fd);
72 static void _ms_get_module_addr(int fd, intptr_t *module_addr);
73 static void _ms_check_idle_state(void);
74 static gpointer _ms_diag_check_idle_state_thread(gpointer data);
75 static gpointer _ms_diag_check_connection_event_thread(gpointer data);
76 static void _ms_lock_state(void);
77 static void _ms_unlock_state(void);
78 static gboolean _ms_connection_handler(GIOChannel *source, GIOCondition condition, gpointer data);
79 static void _ms_diag_init(void);
80 static void _ms_diag_deinit(void);
81 static gboolean _ms_idle_cb(gpointer data);
82 static int _ms_open_lockfile(void);
83 static void _ms_process_init(void);
84 static void _ms_launch_foreground(void);
85 static void _ms_daemonize(void);
88 static void _ms_wait_event(void);
90 static void _ms_wait_event(void)
92 const char *lw_event_list[] = { "/run/.wm_ready", "/tmp/avoc_ready" };
93 unsigned int count = sizeof(lw_event_list) / sizeof(char *);
95 if (LwipcWaitMultiEvents(lw_event_list, count, true, MUSE_LWIPC_WAIT_TIME, NULL, 0) != 0)
96 LOGE("Fail to receive Multiple Events");
100 static bool _ms_attach(int fd, muse_module_callback connection_handler, gpointer module_idx)
102 GIOChannel *channel = NULL;
107 muse_return_val_if_fail(muse_server, false);
108 muse_return_val_if_fail(muse_core_fd_is_valid(fd), false);
110 channel = g_io_channel_unix_new(fd);
111 muse_return_val_if_fail(channel, false);
113 src = g_io_create_watch(channel, G_IO_IN);
115 LOGE("g_io_create_watch() is failed");
116 g_io_channel_unref(channel);
120 g_source_set_callback(src, G_SOURCE_FUNC(connection_handler), module_idx, NULL);
122 if (g_source_attach(src, g_main_loop_get_context(muse_server->main_loop)) == 0) {
123 LOGE("g_source_attach() is failed");
124 g_io_channel_unref(channel);
130 g_io_channel_unref(channel);
137 static void _ms_create_new_server_from_fd(int fd[], int type)
140 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
144 muse_return_if_fail(muse_server);
146 muse_server->msg_fd = fd[MUSE_CHANNEL_MSG];
147 muse_server->data_fd = fd[MUSE_CHANNEL_DATA];
148 muse_server->type = type;
150 for (i = 0; i < MUSE_CHANNEL_MAX; i++) {
151 if (!_ms_attach(fd[i], _ms_connection_handler, GINT_TO_POINTER(i))) {
152 snprintf(err_msg, sizeof(err_msg), "Fail to attach server fd %d", fd[i]);
155 ms_terminate(SIGABRT);
162 static int _ms_new(muse_channel_e channel)
166 struct sockaddr_un addr_un;
167 socklen_t address_len;
168 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
170 muse_return_val_if_fail(channel < MUSE_CHANNEL_MAX, MM_ERROR_INVALID_ARGUMENT);
172 unlink(UDS_files[channel]);
175 fd = socket(AF_UNIX, SOCK_STREAM, 0); /* Unix Domain Socket */
176 if (!muse_core_fd_is_valid(fd)) {
177 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
178 LOGE("socket failed sock (%d) : %s", errno, err_msg);
182 LOGD("muse server fd : %d", fd);
184 memset(&addr_un, 0, sizeof(addr_un));
185 addr_un.sun_family = AF_UNIX;
186 strncpy(addr_un.sun_path, UDS_files[channel], sizeof(addr_un.sun_path) - 1);
187 address_len = (socklen_t)sizeof(addr_un);
189 if (!muse_server->daemonize)
192 /* Bind to filename */
193 if (bind(fd, (struct sockaddr *)&addr_un, address_len) < 0) {
195 strerror_r(errsv, err_msg, MUSE_MSG_LEN_MAX);
196 LOGE("[%d] socket bind failed (%d) %s", fd, errsv, err_msg);
197 muse_core_log_file_list(UDS_files[channel]);
198 ms_log_user_group_info();
199 if (errsv == EADDRINUSE)
200 unlink(addr_un.sun_path);
205 /* Setup listen queue */
206 if (listen(fd, 5) == MUSE_ERR) {
207 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
208 LOGE("[%d] listen() failed (%d) %s", fd, errno, err_msg);
209 muse_core_log_file_list(UDS_files[channel]);
210 ms_log_user_group_info();
215 if (muse_core_set_nonblocking(fd, false) < 0) /* blocking */
216 LOGE("failed to set server socket to blocking");
218 if (!muse_server->daemonize)
224 static int _ms_get_pid(int fd)
226 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
227 struct ucred credentials;
230 length = (socklen_t)sizeof(struct ucred);
231 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &credentials, &length) < 0) {
232 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
233 LOGE("failed to get the value of credential type %s", err_msg);
237 muse_core_update_fd_state(fd);
239 return credentials.pid;
242 static void _ms_get_module_addr(int fd, intptr_t *module_addr)
247 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
248 char recv_buf[MUSE_MSG_LEN_MAX] = {'\0',};
251 if (muse_core_msg_recv_fd(fd, recv_buf, MUSE_MSG_LEN_MAX, NULL) <= 0) {
252 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
253 LOGE("failed to receive message for module %s", err_msg);
257 jobj = muse_core_msg_object_new(recv_buf, NULL, NULL);
259 ret = muse_core_msg_object_get_value(MSG_KEY_MODULE_ADDR, jobj, MUSE_TYPE_POINTER, module_addr);
260 muse_core_msg_object_free(jobj);
262 LOGE("[%d] Error - module_addr %s", try_count, recv_buf);
266 } while (++try_count < MS_RECV_TRY_COUNT_MAX);
269 static gboolean _ms_connection_handler(GIOChannel *source, GIOCondition condition, gpointer data)
271 int server_sockfd = -1;
272 int client_sockfd = -1;
276 socklen_t client_len;
277 struct sockaddr_un client_address;
278 muse_channel_e channel = GPOINTER_TO_INT(data);
279 muse_module_h m = NULL;
280 muse_module_h peeked_m = NULL;
281 muse_module_h candidate_m = NULL;
282 intptr_t module_addr = 0;
283 GQueue *instance_queue = NULL;
284 ms_system_t *system = NULL;
285 ms_connection_t *connection = NULL;
286 char time_buf[MUSE_MSG_TIME_LEN];
288 muse_return_val_if_fail(channel == MUSE_CHANNEL_MSG || channel == MUSE_CHANNEL_DATA, FALSE);
290 LOGI("Enter [%s channel]", channel_name[channel]);
292 muse_return_val_if_fail(muse_server, FALSE);
294 system = muse_server->system;
295 muse_return_val_if_fail(system, FALSE);
297 ms_system_stat_detach(system);
299 connection = muse_server->connection;
300 muse_return_val_if_fail(connection, FALSE);
304 if (muse_server->state != MUSE_SERVER_STATE_READY) {
305 LOGW("Now mused state is not ready...");
309 server_sockfd = g_io_channel_unix_get_fd(source);
310 if (!muse_core_fd_is_valid(server_sockfd)) {
311 LOGE("Critical Error : server %d is invalid", server_sockfd);
315 client_len = (socklen_t)sizeof(client_address);
317 LOGI("[%d] Try to accept...", server_sockfd);
318 client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);
319 if (!muse_core_fd_is_valid(client_sockfd)) {
320 LOGE("Critical Error : accept %d is invalid", client_sockfd);
324 LOGI("server : %d client [%s channel] : %d", server_sockfd, channel_name[channel], client_sockfd);
326 pid = _ms_get_pid(client_sockfd);
330 if (channel == MUSE_CHANNEL_MSG) {
331 m = g_new0(muse_module_t, 1);
332 SECURE_LOGI("module [%p]", m);
333 m->ch[MUSE_CHANNEL_MSG].sock_fd = client_sockfd;
335 g_mutex_init(&m->dispatch_lock);
337 ms_ipc_create_msg_dispatch_worker(m);
340 _ms_get_module_addr(client_sockfd, &module_addr);
342 ms_connection_lock(connection);
344 instance_queue = connection->instance_q;
345 len = g_queue_get_length(instance_queue);
347 m = (muse_module_h)module_addr;
349 for (idx = 0; idx < len; idx++) {
350 peeked_m = (muse_module_h)g_queue_peek_nth(instance_queue, idx);
352 LOGW("[%d] Make sure if the queue length is changed (%d = %d), which means that it was destroyed somewhere",
353 idx, len, g_queue_get_length(instance_queue));
357 if (peeked_m->pid != pid)
362 LOGE("muse-server can't support the error case which there are several modules now");
363 ms_connection_unlock(connection);
367 if (!muse_core_fd_is_valid(peeked_m->ch[MUSE_CHANNEL_DATA].sock_fd))
368 candidate_m = peeked_m;
370 SECURE_LOGW("already paired module %p", peeked_m);
378 if (muse_core_fd_is_valid(m->ch[MUSE_CHANNEL_DATA].sock_fd)) {
379 SECURE_LOGE("[%d] %s pid %d %p you had better check if instance destroy completed properly",
380 client_sockfd, ms_config_get_host_name(m->idx), pid, m);
381 ms_connection_unlock(connection);
385 m->ch[MUSE_CHANNEL_DATA].sock_fd = client_sockfd;
386 SECURE_LOGI("%s (pid %d) module : %p module addr from client : %p",
387 ms_config_get_host_name(m->idx), pid, m, (void *)module_addr);
393 m->ch[MUSE_CHANNEL_DATA].sock_fd = client_sockfd;
394 SECURE_LOGW("[%d] %s pid %d %p restore module address at the only one null data channel",
395 client_sockfd, ms_config_get_host_name(m->idx), pid, m);
398 ms_connection_unlock(connection);
400 ms_ipc_create_data_dispatch_worker(m);
403 muse_core_get_cur_time(&muse_server->tv, NULL);
404 muse_core_change_time_format((int)muse_server->tv.tv_sec, time_buf);
405 LOGW("connected time (%s)", time_buf);
413 if (muse_core_fd_is_valid(server_sockfd))
414 close(server_sockfd);
415 if (muse_core_fd_is_valid(client_sockfd))
416 close(client_sockfd);
419 muse_core_connection_close(m->ch[MUSE_CHANNEL_MSG].sock_fd);
425 ms_terminate(SIGABRT);
430 static void _ms_check_idle_state(void)
432 ms_connection_t *connection = NULL;
433 ms_config_t *conf = NULL;
434 int instance_number, period;
435 uint32_t elapsed_time;
437 static int period_idx = 1;
438 char time_buf[MUSE_MSG_TIME_LEN];
440 muse_return_if_fail(muse_server);
441 muse_return_if_fail(ms_is_server_ready());
443 connection = muse_server->connection;
444 muse_return_if_fail(connection);
446 conf = muse_server->conf;
447 muse_return_if_fail(conf);
449 period = ms_config_get_log_period();
451 if (muse_server->tv.tv_sec == 0)
454 muse_core_get_cur_time(&tv, NULL);
456 elapsed_time = (uint32_t)(tv.tv_sec - muse_server->tv.tv_sec);
458 ms_connection_lock(connection);
460 instance_number = g_queue_get_length(connection->instance_q);
462 if (elapsed_time >= (uint32_t)(period * period_idx)) {
463 muse_core_change_time_format((int)muse_server->tv.tv_sec, time_buf);
464 LOGW("[#%d] %us [period %ds] [%s] total number of modules = %d ( %s)", period_idx,
465 elapsed_time, period, time_buf, instance_number, muse_server->instance_pid_info);
469 ms_connection_unlock(connection);
471 if (conf->is_on_demand) {
472 if (instance_number == 0 && elapsed_time >= (uint32_t)ms_config_get_max_idle_time()) {
473 LOGE("Timeout exit !!! [Idle time] %u sec", elapsed_time);
474 ms_remove_ready_file();
480 static gpointer _ms_diag_check_idle_state_thread(gpointer data)
482 int idle_state_wait_time = ms_config_get_idle_state_wait_time();
484 muse_return_val_if_fail(muse_server, NULL);
485 muse_return_val_if_fail(idle_state_wait_time > 0, NULL);
487 while (ms_is_server_ready()) {
488 _ms_check_idle_state();
489 ms_check_stdin_close();
490 sleep(idle_state_wait_time);
496 static gpointer _ms_diag_check_connection_event_thread(gpointer data)
499 ms_diag_msg_t *dm = NULL;
500 muse_return_val_if_fail(muse_server, NULL);
502 d = &muse_server->diag;
504 while (ms_is_server_ready()) {
505 dm = (ms_diag_msg_t *)g_async_queue_pop(d->msg_aq);
507 LOGD("[%p] POP message (thread stop ? %d [%s])", dm, dm->thread_stop, ms_get_command_string(dm->cmd));
509 if (dm->thread_stop) {
514 if (dm->cmd == API_CREATE) {
515 /* can be updated if connection at the next patch */
516 } else if (dm->cmd == API_DESTROY) {
517 if (ms_config_is_check_cpu_memory())
518 ms_check_cpu_memory();
527 static void _ms_lock_state(void)
529 muse_return_if_fail(muse_server);
530 g_mutex_lock(&muse_server->state_lock);
533 static void _ms_unlock_state(void)
535 muse_return_if_fail(muse_server);
536 g_mutex_unlock(&muse_server->state_lock);
539 static void _ms_diag_init(void)
542 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
543 GError *error = NULL;
545 muse_return_if_fail(muse_server);
547 d = &muse_server->diag;
549 d->idle_state_thread = g_thread_try_new("mused:diag:idle",
550 _ms_diag_check_idle_state_thread, muse_server->main_loop, &error);
551 if (!d->idle_state_thread) {
552 snprintf(err_msg, sizeof(err_msg), "diag_idle_state_thread creation failed : %s", error->message);
555 ms_log_process_info(muse_server->pid);
558 d->msg_aq = g_async_queue_new_full(g_free);
560 d->conn_event_thread = g_thread_try_new("mused:diag:conn",
561 _ms_diag_check_connection_event_thread, muse_server->main_loop, &error);
562 if (!d->conn_event_thread) {
563 snprintf(err_msg, sizeof(err_msg), "diag_connection_event_thread creation failed : %s", error->message);
566 ms_log_process_info(muse_server->pid);
570 static void _ms_diag_deinit(void)
577 muse_return_if_fail(muse_server);
579 d = &muse_server->diag;
581 dm = g_new0(ms_diag_msg_t, 1);
583 dm->thread_stop = TRUE;
584 LOGI("[%p] g_async_queue_push", dm);
585 g_async_queue_push_front(d->msg_aq, (gpointer)dm);
587 if (d->idle_state_thread) {
588 g_thread_join(d->idle_state_thread);
589 d->idle_state_thread = NULL;
592 if (d->conn_event_thread) {
593 g_thread_join(d->conn_event_thread);
594 d->conn_event_thread = NULL;
597 g_async_queue_unref(d->msg_aq);
601 static gboolean _ms_idle_cb(gpointer data)
604 char time_buf[MUSE_MSG_TIME_LEN];
606 if (!ms_create_ready_file())
607 LOGE("%s file creation is failed", MUSE_SERVER_READY);
611 muse_core_get_cur_time(&tv, NULL);
613 muse_core_change_time_format((int)tv.tv_sec, time_buf);
615 LOGW("muse server is completed to ready (%s)", time_buf);
617 return G_SOURCE_REMOVE;
620 static void _ms_init(void)
626 #if defined (__aarch64__) || defined (__x86_64__)
627 mallopt(M_MMAP_THRESHOLD, MUSE_DEFAULT_MMAP_THRESHOLD_MAX);
628 mallopt(M_TRIM_THRESHOLD, 2 * MUSE_DEFAULT_MMAP_THRESHOLD_MAX);
631 muse_server->system = g_new0(ms_system_t, 1);
632 ms_system_init(muse_server->system);
634 muse_server->conf = g_new0(ms_config_t, 1);
635 ms_config_init(muse_server->conf);
637 muse_server->log = g_new0(ms_log_t, 1);
638 ms_log_init(muse_server->log);
640 muse_server->security = g_new0(ms_security_t, 1);
641 ms_security_init(muse_server->security);
643 for (idx = 0; idx < muse_server->conf->host_cnt; idx++) {
644 muse_server->module[idx] = g_new0(ms_module_t, 1);
645 muse_server->module[idx]->idx = idx;
646 ms_module_init(muse_server->module[idx]);
649 #ifdef MUSE_USE_WATCHDOG
650 muse_server->watchdog = g_new0(ms_watchdog_t, 1);
651 if (ms_watchdog_init(muse_server->watchdog) != MM_ERROR_NONE)
652 LOGE("Fail to initialize server watchdog");
655 muse_server->connection = g_new0(ms_connection_t, 1);
656 ms_connection_init(muse_server->connection);
660 g_mutex_init(&muse_server->state_lock);
662 muse_core_create_fd_table();
664 muse_server->main_loop = g_main_loop_new(NULL, FALSE);
665 muse_return_if_fail(muse_server->main_loop);
670 static int _ms_open_lockfile(void)
672 int fd, already_running;
673 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
674 char *lockfile = NULL;
676 muse_return_val_if_fail(muse_server, MUSE_ERR);
678 lockfile = ms_config_get_lockfile();
679 muse_return_val_if_fail(lockfile, MUSE_ERR);
681 muse_core_remove_symlink((const char *)lockfile);
682 fd = open(lockfile, O_RDONLY);
683 if (fd == -1 && errno != ENOENT) {
684 /* Cannot open file even though file exists. */
685 snprintf(err_msg, sizeof(err_msg), "Cannot open lock file %s", lockfile);
686 LOGE("open failed : %s", err_msg);
688 } else if (fd != -1) {
689 already_running = flock(fd, LOCK_EX | LOCK_NB) == -1;
691 if (already_running) {
692 LOGE("File already locked. There's already a server running");
697 /* Lock file does not exist, or is not locked. Create a new lockfile and lock it. */
698 fd = open(lockfile, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
700 LOGE("dataserver: Cannot create lock file");
704 if (flock(fd, LOCK_EX | LOCK_NB) != 0) {
705 LOGE("Can't lock the lock file \"%s\". " "Is another instance running?", lockfile);
712 return MM_ERROR_NONE;
715 static void _ms_process_init(void)
717 if (g_mkdir_with_parents(tzplatform_mkpath(TZ_SYS_RUN, "mused"), S_IRWXU | S_IRWXG | S_IRWXO) != 0)
720 if (muse_server->daemonize) {
721 if (ms_pidfile_create(MUSE_DEFAULT_PIDFILE, muse_server->pid) != MM_ERROR_NONE)
724 LOGW("MUSE_DEFAULT_PIDFILE(%s) file was created", MUSE_DEFAULT_PIDFILE);
729 muse_return_if_fail(_ms_open_lockfile() == MM_ERROR_NONE);
734 static void _ms_launch_foreground(void)
736 muse_server->pid = (int)getpid();
741 static void _ms_daemonize(void)
745 muse_server->pid = ms_daemonize(¬ify_fd);
749 ms_daemonize_complete(notify_fd);
752 void ms_setup_syslog(void)
754 int flags = LOG_CONS|LOG_NDELAY|LOG_PID;
755 if (isatty(STDOUT_FILENO))
758 openlog("mused", flags, LOG_DAEMON);
759 LOGD("openlog - mused");
762 void ms_fork(int *notify_fd)
766 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
767 char msg[MUSE_MSG_LEN_MAX] = {'\0',};
769 if (pipe(fds) == MUSE_ERR) {
770 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
771 LOGE("Failed to create pipe to get child status: %s", err_msg);
775 if ((pid = fork()) < 0) {
776 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
777 LOGE("Error: fork() failed: %s", err_msg);
779 } else if (pid != 0) {
781 /* Read in a string from the pipe */
782 if (read(fds[0], msg, sizeof(msg)) <= 0) {
783 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
784 LOGE("Failed to read from a file descriptor [%d] errno %d %s", fds[0], errno, err_msg);
790 /* Parent process closes up output side of pipe */
791 if (!strncmp(msg, MSG_DONE, strlen(MSG_DONE))) {
792 LOGI("Successfully daemonized");
795 LOGE("Daemonizing failed after fork");
798 } else if (pid == 0) {
799 /* Child process closes up input side of pipe */
805 pid_t ms_daemonize(int *notify_fd)
810 muse_return_val_if_fail(notify_fd, MUSE_ERR);
814 if ((pid = setsid()) < 0) {
815 LOGE("create new session");
819 /* change the file mode mask */
823 LOGD("result = %d sid: %d pgid: %d pid: %d ppid: %d", result, (int)getsid(0), (int)getpgid(0), (int)pid, (int)getppid());
825 /* redirect fds to /dev/null */
826 fd = open("/dev/null", O_RDWR);
827 if (!muse_core_fd_is_valid(fd)) {
828 LOGE("Critical Error : %d is invalid", fd);
833 close(STDOUT_FILENO);
834 close(STDERR_FILENO);
836 dup2(fd, STDIN_FILENO);
837 dup2(fd, STDOUT_FILENO);
838 dup2(fd, STDERR_FILENO);
845 void ms_daemonize_complete(int notify_fd)
849 muse_return_if_fail(muse_core_fd_is_valid(notify_fd));
851 write(notify_fd, MSG_DONE, strlen(MSG_DONE) + 1);
852 LOGW("[%d] Notify parent process that child initialization is done", notify_fd);
858 void ms_gst_init(char **cmd)
863 gboolean ret = FALSE;
866 #ifdef MUSE_TTRACE_LOG
867 trace_begin("MUSE:gst_init");
870 gst_param_cnt = ms_config_get_gst_param_cnt();
873 argv = g_malloc0(sizeof(gchar *) * (gst_param_cnt + 1));
875 argv[argc++] = (gchar *)cmd[0];
876 for (; argc <= gst_param_cnt; argc++) {
877 argv[argc] = ms_config_get_gst_param_str(argc - 1);
878 LOGI("%d %s", argc, argv[argc]);
881 /* initializing gstreamer */
882 ret = gst_init_check(&argc, &argv, &err);
884 LOGE("Could not initialize GStreamer: %s ", err ? err->message : "unknown error occurred");
889 LOGI("gst_init_check is completed");
894 LOGI("complete to initialize gstreamer");
896 #ifdef MUSE_TTRACE_LOG
901 void ms_gst_preload_plugin(void)
904 char *saveptr = NULL;
905 char plugin_path[128];
906 const char *delimeters = " ,";
907 gchar *gst_preload_plugins = g_strdup(ms_config_get_gst_preload_plugins());
908 GstPlugin *plugin = NULL;
910 muse_return_if_fail(gst_preload_plugins);
912 LOGI("preload plugins [%s]", gst_preload_plugins);
914 token = strtok_r(gst_preload_plugins, delimeters, &saveptr);
916 snprintf(plugin_path, sizeof(plugin_path), "%s/gstreamer-1.0/libgst%s.so", LIBDIR, token);
918 LOGI(" plugin path : %s", plugin_path);
920 plugin = gst_plugin_load_file(plugin_path, NULL);
922 gst_object_unref(plugin);
924 LOGW("failed to load plugin [%s]", plugin_path);
926 token = strtok_r(NULL, delimeters, &saveptr);
929 g_free(gst_preload_plugins);
934 int ms_pidfile_create(const char *path, pid_t pid)
938 char pid_buf[MUSE_MSG_LEN] = {'\0',};
939 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
941 muse_return_val_if_fail(path, MM_ERROR_INVALID_ARGUMENT);
942 muse_core_remove_symlink(path);
943 fd = open(path, O_WRONLY | O_CREAT, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
945 if (!muse_core_fd_is_valid(fd)) {
946 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
947 LOGE("Fail to open pidfile [%s] : %s", path, err_msg);
948 return MM_ERROR_FILE_NOT_FOUND;
951 lock.l_type = F_WRLCK;
953 lock.l_whence = SEEK_SET;
956 if (fcntl(fd, F_SETLK, &lock) < 0) {
957 if (errno != EACCES && errno != EAGAIN) {
958 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
959 LOGE("Fail to lock pidfile [%s] : %s", path, err_msg);
961 LOGE("process is already running");
964 return MM_ERROR_FILE_INTERNAL;
967 if (ftruncate(fd, 0) < 0) {
968 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
969 LOGE("Fail to truncate pidfile [%s] : %s", path, err_msg);
971 return MM_ERROR_FILE_INTERNAL;
974 memset(pid_buf, 0, sizeof(pid_buf));
975 snprintf(pid_buf, sizeof(pid_buf), "%u", pid);
977 if (write(fd, pid_buf, strlen(pid_buf)) != (int)strlen(pid_buf)) {
978 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
979 LOGE("Fail to write pid to pidfile [%s] : %s", path, err_msg);
981 return MM_ERROR_FILE_WRITE;
985 return MM_ERROR_NONE;
988 void ms_init(char **argv)
992 muse_module_cmd_dispatchfunc *cmd_dispatcher = NULL;
996 muse_server = g_new0(muse_server_t, 1);
998 for (idx = 1; argv[idx] != NULL; idx++) {
999 if (strcmp(argv[idx], "-D") == 0) {
1000 LOGI("enable daemonize");
1001 muse_server->daemonize = TRUE;
1007 if (muse_server->daemonize)
1010 _ms_launch_foreground();
1012 muse_server->boost.is_boosted = muse_boosting_start();
1014 #ifdef MUSE_VIP_REGISTERED
1015 proc_stat_set_vip_process();
1018 #ifdef MUSE_TTRACE_LOG
1022 ms_system_subscribe_external_event(muse_server->system);
1024 #ifdef MUSE_USE_WATCHDOG
1025 if (!ms_watchdog_attach(muse_server->watchdog)) {
1026 LOGE("watchdog thread failed");
1027 ms_log_process_info(muse_server->pid);
1036 #ifdef MUSE_TTRACE_LOG
1037 trace_begin("MUSE:preloading module");
1039 for (idx = 0; idx < ms_config_get_host_cnt(); idx++) {
1040 if (0 == strncmp(ms_config_get_preloaded_value(idx), "yes", strlen("yes"))) {
1041 g_module_symbol(ms_module_open(idx), CMD_DISPATCHER, (gpointer *)&cmd_dispatcher);
1042 if (cmd_dispatcher && cmd_dispatcher[MUSE_MODULE_COMMAND_INITIALIZE])
1043 cmd_dispatcher[MUSE_MODULE_COMMAND_INITIALIZE](NULL);
1046 #ifdef MUSE_TTRACE_LOG
1050 #ifdef MUSE_TTRACE_LOG
1051 trace_begin("MUSE:preloading GST module");
1053 ms_gst_preload_plugin();
1054 #ifdef MUSE_TTRACE_LOG
1058 #ifdef MUSE_GCOV_TEST
1059 muse_core_setenv("GCOV_PREFIX", "/tmp", 1);
1062 if (muse_server->boost.is_boosted)
1063 muse_server->boost.is_boosted = !muse_boosting_stop();
1065 muse_server->boost.is_inheritance_registered = muse_boosting_register_cpu_inheritance();
1070 muse_server_h ms_get_instance(void)
1075 gboolean ms_check_module_idx(int idx)
1077 int module_cnt = ms_config_get_host_cnt();
1079 if (idx < 0 || idx >= module_cnt) {
1080 LOGE("%d error - the number of modules is %d", idx, module_cnt);
1087 ms_module_t *ms_get_module_instance(int idx)
1089 muse_return_val_if_fail(ms_check_module_idx(idx), NULL);
1091 return muse_server->module[idx];
1096 int retval = MUSE_ERR;
1101 muse_return_val_if_fail(muse_server, retval);
1102 muse_return_val_if_fail(muse_server->conf, retval);
1103 muse_return_val_if_fail(muse_server->connection, retval);
1104 muse_return_val_if_fail(muse_server->log, retval);
1105 muse_return_val_if_fail(muse_server->security, retval);
1106 muse_return_val_if_fail(muse_server->watchdog, retval);
1108 ms_recursive_rmdir(MUSE_DATA_ROOT_PATH);
1110 ms_set_state(MUSE_SERVER_STATE_IDLE);
1112 if (muse_server->boost.is_inheritance_registered)
1113 muse_server->boost.is_inheritance_registered = !muse_boosting_unregister_cpu_inheritance();
1117 #ifdef MUSE_USE_WATCHDOG
1118 ms_watchdog_detach(muse_server->watchdog);
1120 if (ms_watchdog_deinit(muse_server->watchdog) == MM_ERROR_NONE)
1121 free(muse_server->watchdog);
1123 LOGE("Fail to deinitialize server watchdog");
1126 ms_remove_ready_file();
1128 retval = muse_server->retval;
1129 muse_core_fd_close(muse_server->msg_fd);
1130 muse_core_fd_close(muse_server->data_fd);
1131 for (idx = 0; idx < MUSE_CHANNEL_MAX; idx++) {
1132 if (remove(UDS_files[idx]) == MUSE_ERR)
1133 LOGE("remove %s failed", UDS_files[idx]);
1136 if (remove(MUSE_DEFAULT_PIDFILE) == -1)
1137 LOGE("remove %s failed [errno : %d]", MUSE_DEFAULT_PIDFILE, errno);
1139 for (idx = 0; idx < muse_server->conf->host_cnt; idx++)
1140 ms_module_deinit(muse_server->module[idx]);
1142 ms_security_deinit(muse_server->security);
1143 muse_server->security = NULL;
1145 ms_system_deinit(muse_server->system);
1146 muse_server->system = NULL;
1148 ms_log_deinit(muse_server->log);
1149 muse_server->log = NULL;
1151 ms_config_deinit(muse_server->conf);
1152 muse_server->conf = NULL;
1154 ms_connection_deinit(muse_server->connection);
1155 muse_server->connection = NULL;
1157 muse_core_destroy_fd_table();
1161 g_mutex_clear(&muse_server->state_lock);
1163 g_free(muse_server);
1170 void ms_check_cpu_memory(void)
1172 int used_pss, memory_threshold, cpu_usage, cpu_threshold;
1173 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
1174 ms_connection_t *connection = NULL;
1175 ms_system_t *system = NULL;
1177 muse_return_if_fail(muse_server);
1179 connection = muse_server->connection;
1180 muse_return_if_fail(connection);
1182 system = muse_server->system;
1183 muse_return_if_fail(system);
1185 ms_connection_lock(connection);
1187 if (g_queue_is_empty(connection->instance_q) && ms_is_server_ready()) {
1188 used_pss = ms_system_get_memory_usage(muse_server->pid);
1189 cpu_usage = muse_core_get_process_cpu_usage(muse_server->pid);
1191 LOGW("[%d] Proportional set size %d (KByte) (CPU %d %%)", muse_server->pid, used_pss, cpu_usage);
1193 memory_threshold = ms_config_get_memory_threshold();
1194 cpu_threshold = ms_config_get_cpu_threshold();
1196 if (used_pss >= memory_threshold) {
1197 ms_log_process_info(muse_server->pid);
1199 snprintf(err_msg, sizeof(err_msg), "[Memory Leak] %d >= %d (KByte)", used_pss, memory_threshold);
1201 LOGE("%s", err_msg);
1202 ms_connection_unlock(connection);
1203 ms_terminate(SIGTERM);
1206 if (cpu_usage > cpu_threshold)
1207 ms_system_stat_attach(system);
1209 muse_core_remove_all_fd_table();
1211 LOGI("skip cpu memory check due to instance queue length : %d", g_queue_get_length(connection->instance_q));
1214 ms_connection_unlock(connection);
1217 void ms_check_stdin_close(void)
1219 ms_connection_t *connection = muse_server->connection;
1220 muse_return_if_fail(connection);
1222 ms_connection_lock(connection);
1224 if (fcntl(STDIN_FILENO, F_GETFD) == -1 && errno == EBADF)
1225 LOGE("stdin is closed.");
1227 ms_connection_unlock(connection);
1232 int fd[MUSE_CHANNEL_MAX];
1235 for (i = 0; i < MUSE_CHANNEL_MAX; i++) {
1236 if (ms_config_is_on_demand() && i == MUSE_CHANNEL_MSG)
1237 fd[i] = SD_LISTEN_FDS_START;
1241 if (!muse_core_fd_is_valid(fd[i])) {
1242 LOGE("Failed to create socket server %d", i);
1243 for (j = 0; j < i; j++)
1249 _ms_create_new_server_from_fd(fd, READ | PERSIST);
1256 muse_return_if_fail(muse_server->main_loop);
1258 muse_return_if_fail(g_idle_add_full(G_PRIORITY_HIGH, _ms_idle_cb, NULL, NULL) > 0);
1260 LOGI("g_main_loop_run");
1261 g_main_loop_run(muse_server->main_loop);
1266 void ms_cmd_dispatch(muse_module_h m, muse_module_command_e cmd)
1268 muse_module_cmd_dispatchfunc *cmd_dispatcher = NULL;
1270 if (m->ch[MUSE_CHANNEL_MSG].dll_handle &&
1271 g_module_symbol(m->ch[MUSE_CHANNEL_MSG].dll_handle, CMD_DISPATCHER, (gpointer *)&cmd_dispatcher)) {
1272 if (cmd_dispatcher && cmd_dispatcher[cmd])
1273 cmd_dispatcher[cmd](m);
1277 void ms_terminate(int signo)
1279 muse_return_if_fail(muse_server);
1281 ms_set_state(MUSE_SERVER_STATE_IDLE);
1283 LOGE("send signal %d to process %d", signo, muse_server->pid);
1287 int ms_get_pid(muse_module_h m)
1289 muse_return_val_if_fail(m, MUSE_ERR);
1293 void ms_log_process_info(int pid)
1295 muse_core_log_process_thread_info(pid);
1297 muse_core_log_process_opened_fds(pid);
1299 muse_core_log_process_cpu_memory(pid);
1302 void ms_log_user_group_info(void)
1306 char buffer[MUSE_MSG_MAX_LENGTH];
1307 struct passwd pwbuf;
1308 struct passwd *pwbufp;
1310 struct group *gbufp;
1315 getpwuid_r(uid, &pwbuf, buffer, sizeof(buffer), &pwbufp);
1316 muse_return_if_fail(pwbufp);
1318 getgrgid_r(gid, &gbuf, buffer, sizeof(buffer), &gbufp);
1319 muse_return_if_fail(gbufp);
1321 LOGE("user [%s : %lu] group [%s : %lu]", pwbufp->pw_name, (unsigned long)uid, gbufp->gr_name, (unsigned long)gid);
1324 gboolean ms_is_log_enabled(void)
1326 return ms_config_is_log_enabled();
1329 gboolean ms_init_bufmgr(void)
1333 muse_return_val_if_fail(muse_server, FALSE);
1335 muse_server->bufmgr = tbm_bufmgr_init(-1);
1336 if (!muse_server->bufmgr) {
1337 LOGE("Error - tbm_bufmgr_init");
1338 ms_log_user_group_info();
1342 LOGD("Leave bufmgr: %p", muse_server->bufmgr);
1347 void ms_deinit_bufmgr(void)
1351 muse_return_if_fail(muse_server);
1352 muse_return_if_fail(muse_server->bufmgr);
1354 tbm_bufmgr_deinit(muse_server->bufmgr);
1359 void ms_cmd_dispatch_foreach_func(gpointer data, gpointer user_data)
1361 muse_module_h m = (muse_module_h)data;
1362 ms_cmd_dispatcher_info_t *dispatch = (ms_cmd_dispatcher_info_t *)user_data;
1363 muse_module_command_e cmd;
1364 muse_external_storage_info_t *storage;
1366 muse_return_if_fail(muse_server);
1367 muse_return_if_fail(m);
1368 muse_return_if_fail(dispatch);
1370 cmd = dispatch->cmd;
1372 if (cmd == MUSE_MODULE_COMMAND_EXTERNAL_STORAGE_STATE_CHANGED) {
1373 storage = &dispatch->storage;
1374 LOGD("external storage id %d state %d path %s", storage->id, storage->state, storage->path);
1375 muse_server_set_user_data(m, (void *)storage);
1378 ms_cmd_dispatch(m, cmd);
1379 SECURE_LOGI("[%s] module %p (%s)", module_cmd[cmd], m, muse_server->conf->host[m->idx]);
1381 if (cmd == MUSE_MODULE_COMMAND_EXTERNAL_STORAGE_STATE_CHANGED)
1382 muse_server_set_user_data(m, NULL);
1385 void ms_set_state(ms_state_e state)
1387 muse_return_if_fail(muse_server);
1389 g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&muse_server->state_lock);
1391 muse_server->state = state;
1394 gboolean ms_is_server_ready(void)
1396 muse_return_val_if_fail(muse_server, FALSE);
1398 g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&muse_server->state_lock);
1400 return muse_server->state == MUSE_SERVER_STATE_READY;
1403 gboolean ms_create_ready_file(void)
1406 #ifndef MUSE_USE_LWIPC
1410 #ifdef MUSE_USE_LWIPC
1413 ms_set_state(MUSE_SERVER_STATE_READY);
1415 if (LwipcEventDone(MUSE_SERVER_READY) < 0) {
1416 LOGE("Fail to send server ready done event");
1420 ready_fd = creat(MUSE_SERVER_READY, 0644);
1421 if (muse_core_fd_is_valid(ready_fd)) {
1422 LOGD("MUSE_SERVER_READY(%s) file was created", MUSE_SERVER_READY);
1425 ms_set_state(MUSE_SERVER_STATE_READY);
1427 LOGE("[%d] Fail to create MUSE_SERVER_READY(%s)", ready_fd, MUSE_SERVER_READY);
1437 void ms_remove_ready_file(void)
1439 #ifdef MUSE_USE_LWIPC
1440 LwipcResetEvent(MUSE_SERVER_READY);
1442 unlink(MUSE_SERVER_READY);
1443 unlink(MUSE_DEFAULT_PIDFILE);
1447 const char *ms_get_command_string(int cmd)
1449 if (cmd == API_CREATE)
1451 else if (cmd == API_DESTROY)
1452 return "disconnect";
1454 LOGE("Invalid value of cmd (%d)", cmd);
1456 return "Invalid value of cmd";
1459 gboolean ms_module_idx_is_valid(muse_module_h m)
1461 return (m->idx >= 0 && m->idx < ms_config_get_host_cnt());