fixup! Fix coverity issue of MISSING_LOCK
[platform/core/multimedia/mmsvc-core.git] / server / src / muse_server_private.c
1 /*
2  * muse-server
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: YoungHun Kim <yh8004.kim@samsung.com>
7  *
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21
22 #include "muse_server_private.h"
23 #include <sys/file.h>
24 #include <gst/gst.h>
25 #include <syslog.h>
26 #include <malloc.h>
27 #include <tzplatform_config.h>
28
29 #if !GLIB_CHECK_VERSION(2, 58, 0)
30 #define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void)) (f))
31 #endif
32
33 #if defined (__aarch64__) || defined (__x86_64__)
34 #define MUSE_DEFAULT_MMAP_THRESHOLD_MAX (512 * 1024)
35 #endif
36
37
38 #ifdef MUSE_VIP_REGISTERED
39 #include <proc_stat.h>
40 #endif
41
42 #ifdef MUSE_USE_LWIPC
43 #include <lwipc.h>
44 #define MUSE_LWIPC_WAIT_TIME                    1000
45 #endif
46
47
48 static const char *channel_name[MUSE_CHANNEL_MAX] = {
49         "msg",
50         "data"
51 };
52
53 static const char *UDS_files[MUSE_CHANNEL_MAX] = {MUSE_MSG_SOCK, MUSE_DATA_SOCK};
54
55 static muse_server_h muse_server;
56
57 static const char *module_cmd[MUSE_MODULE_COMMAND_MAX] = {
58         "initialize",
59         "shutdown",
60         "debug_info_dump",
61         "create_server_ack",
62         "resource_not_available",
63         "external_storage_state_changed",
64         "create_caution",
65         "resource_manager_shutdown"
66 };
67
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);
86
87 #ifdef MUSE_USE_LWIPC
88 static void _ms_wait_event(void);
89
90 static void _ms_wait_event(void)
91 {
92         const char *lw_event_list[] = { "/run/.wm_ready", "/tmp/avoc_ready" };
93         unsigned int count = sizeof(lw_event_list) / sizeof(char *);
94
95         if (LwipcWaitMultiEvents(lw_event_list, count, true, MUSE_LWIPC_WAIT_TIME, NULL, 0) != 0)
96                 LOGE("Fail to receive Multiple Events");
97 }
98 #endif
99
100 static bool _ms_attach(int fd, muse_module_callback connection_handler, gpointer module_idx)
101 {
102         GIOChannel *channel = NULL;
103         GSource *src = NULL;
104
105         LOGI("Enter");
106
107         muse_return_val_if_fail(muse_server, false);
108         muse_return_val_if_fail(muse_core_fd_is_valid(fd), false);
109
110         channel = g_io_channel_unix_new(fd);
111         muse_return_val_if_fail(channel, false);
112
113         src = g_io_create_watch(channel, G_IO_IN);
114         if (!src) {
115                 LOGE("g_io_create_watch() is failed");
116                 g_io_channel_unref(channel);
117                 return false;
118         }
119
120         g_source_set_callback(src, G_SOURCE_FUNC(connection_handler), module_idx, NULL);
121
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);
125                 return false;
126         }
127
128         g_source_unref(src);
129
130         g_io_channel_unref(channel);
131
132         LOGI("Leave");
133
134         return true;
135 }
136
137 static void _ms_create_new_server_from_fd(int fd[], int type)
138 {
139         int i;
140         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
141
142         LOGD("Enter");
143
144         muse_return_if_fail(muse_server);
145
146         muse_server->msg_fd = fd[MUSE_CHANNEL_MSG];
147         muse_server->data_fd = fd[MUSE_CHANNEL_DATA];
148         muse_server->type = type;
149
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]);
153
154                         LOGE("%s", err_msg);
155                         ms_terminate(SIGABRT);
156                 }
157         }
158
159         LOGD("Leave");
160 }
161
162 static int _ms_new(muse_channel_e channel)
163 {
164         int fd, errsv;
165         mode_t m = 0;
166         struct sockaddr_un addr_un;
167         socklen_t address_len;
168         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
169
170         muse_return_val_if_fail(channel < MUSE_CHANNEL_MAX, MM_ERROR_INVALID_ARGUMENT);
171
172         unlink(UDS_files[channel]);
173
174         /* Create Socket */
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);
179                 return MUSE_ERR;
180         }
181
182         LOGD("muse server fd : %d", fd);
183
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);
188
189         if (!muse_server->daemonize)
190                 m = umask(0);
191
192         /* Bind to filename */
193         if (bind(fd, (struct sockaddr *)&addr_un, address_len) < 0) {
194                 errsv = errno;
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);
201                 close(fd);
202                 return MUSE_ERR;
203         }
204
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();
211                 close(fd);
212                 return MUSE_ERR;
213         }
214
215         if (muse_core_set_nonblocking(fd, false) < 0) /* blocking */
216                 LOGE("failed to set server socket to blocking");
217
218         if (!muse_server->daemonize)
219                 umask(m);
220
221         return fd;
222 }
223
224 static int _ms_get_pid(int fd)
225 {
226         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
227         struct ucred credentials;
228         socklen_t length;
229
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);
234                 return MUSE_ERR;
235         }
236
237         muse_core_update_fd_state(fd);
238
239         return credentials.pid;
240 }
241
242 static void _ms_get_module_addr(int fd, intptr_t *module_addr)
243 {
244         void *jobj;
245         int try_count = 0;
246         bool ret = true;
247         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
248         char recv_buf[MUSE_MSG_LEN_MAX] = {'\0',};
249
250         do {
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);
254                         return;
255                 }
256
257                 jobj = muse_core_msg_object_new(recv_buf, NULL, NULL);
258                 if (jobj) {
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);
261                         if (!ret)
262                                 LOGE("[%d] Error - module_addr %s", try_count, recv_buf);
263                         else
264                                 break;
265                 }
266         } while (++try_count < MS_RECV_TRY_COUNT_MAX);
267 }
268
269 static gboolean _ms_connection_handler(GIOChannel *source, GIOCondition condition, gpointer data)
270 {
271         int server_sockfd = -1;
272         int client_sockfd = -1;
273         int pid;
274         int idx;
275         int len;
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];
287
288         muse_return_val_if_fail(channel == MUSE_CHANNEL_MSG || channel == MUSE_CHANNEL_DATA, FALSE);
289
290         LOGI("Enter [%s channel]", channel_name[channel]);
291
292         muse_return_val_if_fail(muse_server, FALSE);
293
294         system = muse_server->system;
295         muse_return_val_if_fail(system, FALSE);
296
297         ms_system_stat_detach(system);
298
299         connection = muse_server->connection;
300         muse_return_val_if_fail(connection, FALSE);
301
302         _ms_lock_state();
303
304         if (muse_server->state != MUSE_SERVER_STATE_READY) {
305                 LOGW("Now mused state is not ready...");
306                 goto out;
307         }
308
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);
312                 goto out;
313         }
314
315         client_len = (socklen_t)sizeof(client_address);
316
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);
321                 goto out;
322         }
323
324         LOGI("server : %d client [%s channel] : %d", server_sockfd, channel_name[channel], client_sockfd);
325
326         pid = _ms_get_pid(client_sockfd);
327         if (pid == -1)
328                 goto out;
329
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;
334                 m->pid = pid;
335                 g_mutex_init(&m->dispatch_lock);
336
337                 ms_ipc_create_msg_dispatch_worker(m);
338
339         } else {
340                 _ms_get_module_addr(client_sockfd, &module_addr);
341
342                 ms_connection_lock(connection);
343
344                 instance_queue = connection->instance_q;
345                 len = g_queue_get_length(instance_queue);
346
347                 m = (muse_module_h)module_addr;
348
349                 for (idx = 0; idx < len; idx++) {
350                         peeked_m = (muse_module_h)g_queue_peek_nth(instance_queue, idx);
351                         if (!peeked_m) {
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));
354                                 continue;
355                         }
356
357                         if (peeked_m->pid != pid)
358                                 continue;
359
360                         if (!m) {
361                                 if (candidate_m) {
362                                         LOGE("muse-server can't support the error case which there are several modules now");
363                                         ms_connection_unlock(connection);
364                                         goto out;
365                                 }
366
367                                 if (!muse_core_fd_is_valid(peeked_m->ch[MUSE_CHANNEL_DATA].sock_fd))
368                                         candidate_m = peeked_m;
369                                 else
370                                         SECURE_LOGW("already paired module %p", peeked_m);
371
372                                 continue;
373                         }
374
375                         if (m != peeked_m)
376                                 continue;
377
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);
382                                 goto out;
383                         }
384
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);
388                         break;
389                 }
390
391                 if (candidate_m) {
392                         m = candidate_m;
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);
396                 }
397
398                 ms_connection_unlock(connection);
399
400                 ms_ipc_create_data_dispatch_worker(m);
401         }
402
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);
406
407         _ms_unlock_state();
408
409         LOGI("Leave");
410
411         return TRUE;
412 out:
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);
417
418         if (m)
419                 muse_core_connection_close(m->ch[MUSE_CHANNEL_MSG].sock_fd);
420
421         _ms_unlock_state();
422
423         LOGE("FALSE");
424
425         ms_terminate(SIGABRT);
426
427         return FALSE;
428 }
429
430 static void _ms_check_idle_state(void)
431 {
432         ms_connection_t *connection = NULL;
433         ms_config_t *conf = NULL;
434         int instance_number, period;
435         uint32_t elapsed_time;
436         struct timespec tv;
437         static int period_idx = 1;
438         char time_buf[MUSE_MSG_TIME_LEN];
439
440         muse_return_if_fail(muse_server);
441         muse_return_if_fail(ms_is_server_ready());
442
443         connection = muse_server->connection;
444         muse_return_if_fail(connection);
445
446         conf = muse_server->conf;
447         muse_return_if_fail(conf);
448
449         period = ms_config_get_log_period();
450
451         if (muse_server->tv.tv_sec == 0)
452                 return;
453
454         muse_core_get_cur_time(&tv, NULL);
455
456         elapsed_time = (uint32_t)(tv.tv_sec - muse_server->tv.tv_sec);
457
458         ms_connection_lock(connection);
459
460         instance_number = g_queue_get_length(connection->instance_q);
461
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);
466                 period_idx++;
467         }
468
469         ms_connection_unlock(connection);
470
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();
475                         exit(EXIT_SUCCESS);
476                 }
477         }
478 }
479
480 static gpointer _ms_diag_check_idle_state_thread(gpointer data)
481 {
482         int idle_state_wait_time = ms_config_get_idle_state_wait_time();
483
484         muse_return_val_if_fail(muse_server, NULL);
485         muse_return_val_if_fail(idle_state_wait_time > 0, NULL);
486
487         while (ms_is_server_ready()) {
488                 _ms_check_idle_state();
489                 ms_check_stdin_close();
490                 sleep(idle_state_wait_time);
491         }
492
493         return NULL;
494 }
495
496 static gpointer _ms_diag_check_connection_event_thread(gpointer data)
497 {
498         ms_diag_t *d;
499         ms_diag_msg_t *dm = NULL;
500         muse_return_val_if_fail(muse_server, NULL);
501
502         d = &muse_server->diag;
503
504         while (ms_is_server_ready()) {
505                 dm = (ms_diag_msg_t *)g_async_queue_pop(d->msg_aq);
506
507                 LOGD("[%p] POP message (thread stop ? %d [%s])", dm, dm->thread_stop, ms_get_command_string(dm->cmd));
508
509                 if (dm->thread_stop) {
510                         g_free(dm);
511                         break;
512                 }
513
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();
519                 }
520
521                 g_free(dm);
522         }
523
524         return NULL;
525 }
526
527 static void _ms_lock_state(void)
528 {
529         muse_return_if_fail(muse_server);
530         g_mutex_lock(&muse_server->state_lock);
531 }
532
533 static void _ms_unlock_state(void)
534 {
535         muse_return_if_fail(muse_server);
536         g_mutex_unlock(&muse_server->state_lock);
537 }
538
539 static void _ms_diag_init(void)
540 {
541         ms_diag_t *d;
542         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
543         GError *error = NULL;
544
545         muse_return_if_fail(muse_server);
546
547         d = &muse_server->diag;
548
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);
553                 LOGE("%s", err_msg);
554                 g_error_free(error);
555                 ms_log_process_info(muse_server->pid);
556         }
557
558         d->msg_aq = g_async_queue_new_full(g_free);
559
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);
564                 LOGE("%s", err_msg);
565                 g_error_free(error);
566                 ms_log_process_info(muse_server->pid);
567         }
568 }
569
570 static void _ms_diag_deinit(void)
571 {
572         ms_diag_t *d;
573         ms_diag_msg_t *dm;
574
575         LOGD("Enter");
576
577         muse_return_if_fail(muse_server);
578
579         d = &muse_server->diag;
580
581         dm = g_new0(ms_diag_msg_t, 1);
582
583         dm->thread_stop = TRUE;
584         LOGI("[%p] g_async_queue_push", dm);
585         g_async_queue_push_front(d->msg_aq, (gpointer)dm);
586
587         if (d->idle_state_thread) {
588                 g_thread_join(d->idle_state_thread);
589                 d->idle_state_thread = NULL;
590         }
591
592         if (d->conn_event_thread) {
593                 g_thread_join(d->conn_event_thread);
594                 d->conn_event_thread = NULL;
595         }
596
597         g_async_queue_unref(d->msg_aq);
598         d->msg_aq = NULL;
599 }
600
601 static gboolean _ms_idle_cb(gpointer data)
602 {
603         struct timespec tv;
604         char time_buf[MUSE_MSG_TIME_LEN];
605
606         if (!ms_create_ready_file())
607                 LOGE("%s file creation is failed", MUSE_SERVER_READY);
608
609         _ms_diag_init();
610
611         muse_core_get_cur_time(&tv, NULL);
612
613         muse_core_change_time_format((int)tv.tv_sec, time_buf);
614
615         LOGW("muse server is completed to ready (%s)", time_buf);
616
617         return G_SOURCE_REMOVE;
618 }
619
620 static void _ms_init(void)
621 {
622         int idx;
623
624         LOGD("Enter");
625
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);
629 #endif
630
631         muse_server->system = g_new0(ms_system_t, 1);
632         ms_system_init(muse_server->system);
633
634         muse_server->conf = g_new0(ms_config_t, 1);
635         ms_config_init(muse_server->conf);
636
637         muse_server->log = g_new0(ms_log_t, 1);
638         ms_log_init(muse_server->log);
639
640         muse_server->security = g_new0(ms_security_t, 1);
641         ms_security_init(muse_server->security);
642
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]);
647         }
648
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");
653 #endif
654
655         muse_server->connection = g_new0(ms_connection_t, 1);
656         ms_connection_init(muse_server->connection);
657
658         ms_signal_init();
659
660         g_mutex_init(&muse_server->state_lock);
661
662         muse_core_create_fd_table();
663
664         muse_server->main_loop = g_main_loop_new(NULL, FALSE);
665         muse_return_if_fail(muse_server->main_loop);
666
667         LOGD("Leave");
668 }
669
670 static int _ms_open_lockfile(void)
671 {
672         int fd, already_running;
673         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
674         char *lockfile = NULL;
675
676         muse_return_val_if_fail(muse_server, MUSE_ERR);
677
678         lockfile = ms_config_get_lockfile();
679         muse_return_val_if_fail(lockfile, MUSE_ERR);
680
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);
687                 return MUSE_ERR;
688         } else if (fd != -1) {
689                 already_running = flock(fd, LOCK_EX | LOCK_NB) == -1;
690                 close(fd);
691                 if (already_running) {
692                         LOGE("File already locked. There's already a server running");
693                         return MUSE_ERR;
694                 }
695         }
696
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);
699         if (fd == -1) {
700                 LOGE("dataserver: Cannot create lock file");
701                 return MUSE_ERR;
702         }
703
704         if (flock(fd, LOCK_EX | LOCK_NB) != 0) {
705                 LOGE("Can't lock the lock file \"%s\". " "Is another instance running?", lockfile);
706                 close(fd);
707                 return MUSE_ERR;
708         }
709
710         close(fd);
711
712         return MM_ERROR_NONE;
713 }
714
715 static void _ms_process_init(void)
716 {
717         if (g_mkdir_with_parents(tzplatform_mkpath(TZ_SYS_RUN, "mused"), S_IRWXU | S_IRWXG | S_IRWXO) != 0)
718                 exit(EXIT_FAILURE);
719
720         if (muse_server->daemonize) {
721                 if (ms_pidfile_create(MUSE_DEFAULT_PIDFILE, muse_server->pid) != MM_ERROR_NONE)
722                         exit(EXIT_FAILURE);
723                 else
724                         LOGW("MUSE_DEFAULT_PIDFILE(%s) file was created", MUSE_DEFAULT_PIDFILE);
725         }
726
727         _ms_init();
728
729         muse_return_if_fail(_ms_open_lockfile() == MM_ERROR_NONE);
730
731         ms_new();
732 }
733
734 static void _ms_launch_foreground(void)
735 {
736         muse_server->pid = (int)getpid();
737
738         _ms_process_init();
739 }
740
741 static void _ms_daemonize(void)
742 {
743         int notify_fd;
744
745         muse_server->pid = ms_daemonize(&notify_fd);
746
747         _ms_process_init();
748
749         ms_daemonize_complete(notify_fd);
750 }
751
752 void ms_setup_syslog(void)
753 {
754         int flags = LOG_CONS|LOG_NDELAY|LOG_PID;
755         if (isatty(STDOUT_FILENO))
756                 flags |= LOG_PERROR;
757
758         openlog("mused", flags, LOG_DAEMON);
759         LOGD("openlog - mused");
760 }
761
762 void ms_fork(int *notify_fd)
763 {
764         pid_t pid;
765         int fds[2];
766         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
767         char msg[MUSE_MSG_LEN_MAX] = {'\0',};
768
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);
772                 exit(EXIT_FAILURE);
773         }
774
775         if ((pid = fork()) < 0) {
776                 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
777                 LOGE("Error: fork() failed: %s", err_msg);
778                 exit(EXIT_FAILURE);
779         } else if (pid != 0) {
780                 close(fds[1]);
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);
785                         close(fds[0]);
786                         exit(EXIT_FAILURE);
787                 }
788                 close(fds[0]);
789
790                 /* Parent process closes up output side of pipe */
791                 if (!strncmp(msg, MSG_DONE, strlen(MSG_DONE))) {
792                         LOGI("Successfully daemonized");
793                         exit(EXIT_SUCCESS);
794                 } else {
795                         LOGE("Daemonizing failed after fork");
796                         exit(EXIT_FAILURE);
797                 }
798         } else if (pid == 0) {
799                 /* Child process closes up input side of pipe */
800                 close(fds[0]);
801                 *notify_fd = fds[1];
802         }
803 }
804
805 pid_t ms_daemonize(int *notify_fd)
806 {
807         pid_t pid;
808         int fd, result;
809
810         muse_return_val_if_fail(notify_fd, MUSE_ERR);
811
812         ms_fork(notify_fd);
813
814         if ((pid = setsid()) < 0) {
815                 LOGE("create new session");
816                 exit(EXIT_FAILURE);
817         }
818
819         /* change the file mode mask */
820         umask(0);
821
822         result = chdir("/");
823         LOGD("result = %d sid: %d pgid: %d pid: %d ppid: %d", result, (int)getsid(0), (int)getpgid(0), (int)pid, (int)getppid());
824
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);
829                 exit(EXIT_SUCCESS);
830         }
831
832         close(STDIN_FILENO);
833         close(STDOUT_FILENO);
834         close(STDERR_FILENO);
835
836         dup2(fd, STDIN_FILENO);
837         dup2(fd, STDOUT_FILENO);
838         dup2(fd, STDERR_FILENO);
839
840         close(fd);
841
842         return pid;
843 }
844
845 void ms_daemonize_complete(int notify_fd)
846 {
847         LOGD("Enter");
848
849         muse_return_if_fail(muse_core_fd_is_valid(notify_fd));
850
851         write(notify_fd, MSG_DONE, strlen(MSG_DONE) + 1);
852         LOGW("[%d] Notify parent process that child initialization is done", notify_fd);
853         close(notify_fd);
854
855         LOGD("Leave");
856 }
857
858 void ms_gst_init(char **cmd)
859 {
860         gint argc = 0;
861         gchar **argv = NULL;
862         GError *err = NULL;
863         gboolean ret = FALSE;
864         int gst_param_cnt;
865
866 #ifdef MUSE_TTRACE_LOG
867         trace_begin("MUSE:gst_init");
868 #endif
869
870         gst_param_cnt = ms_config_get_gst_param_cnt();
871
872         /* add gst_param */
873         argv = g_malloc0(sizeof(gchar *) * (gst_param_cnt + 1));
874
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]);
879         }
880
881         /* initializing gstreamer */
882         ret = gst_init_check(&argc, &argv, &err);
883         if (!ret) {
884                 LOGE("Could not initialize GStreamer: %s ", err ? err->message : "unknown error occurred");
885                 if (err)
886                         g_error_free(err);
887         }
888
889         LOGI("gst_init_check is completed");
890
891         /* release */
892         g_free(argv);
893
894         LOGI("complete to initialize gstreamer");
895
896 #ifdef MUSE_TTRACE_LOG
897         trace_end();
898 #endif
899 }
900
901 void ms_gst_preload_plugin(void)
902 {
903         char *token = NULL;
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;
909
910         muse_return_if_fail(gst_preload_plugins);
911
912         LOGI("preload plugins [%s]", gst_preload_plugins);
913
914         token = strtok_r(gst_preload_plugins, delimeters, &saveptr);
915         while (token) {
916                 snprintf(plugin_path, sizeof(plugin_path), "%s/gstreamer-1.0/libgst%s.so", LIBDIR, token);
917
918                 LOGI("    plugin path : %s", plugin_path);
919
920                 plugin = gst_plugin_load_file(plugin_path, NULL);
921                 if (plugin)
922                         gst_object_unref(plugin);
923                 else
924                         LOGW("failed to load plugin [%s]", plugin_path);
925
926                 token = strtok_r(NULL, delimeters, &saveptr);
927         }
928
929         g_free(gst_preload_plugins);
930
931         LOGI("Leave");
932 }
933
934 int ms_pidfile_create(const char *path, pid_t pid)
935 {
936         int fd;
937         struct flock lock;
938         char pid_buf[MUSE_MSG_LEN] = {'\0',};
939         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
940
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));
944
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;
949         }
950
951         lock.l_type = F_WRLCK;
952         lock.l_start = 0;
953         lock.l_whence = SEEK_SET;
954         lock.l_len = 0;
955
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);
960                 } else {
961                         LOGE("process is already running");
962                 }
963                 close(fd);
964                 return MM_ERROR_FILE_INTERNAL;
965         }
966
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);
970                 close(fd);
971                 return MM_ERROR_FILE_INTERNAL;
972         }
973
974         memset(pid_buf, 0, sizeof(pid_buf));
975         snprintf(pid_buf, sizeof(pid_buf), "%u", pid);
976
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);
980                 close(fd);
981                 return MM_ERROR_FILE_WRITE;
982         }
983
984         close(fd);
985         return MM_ERROR_NONE;
986 }
987
988 void ms_init(char **argv)
989 {
990         int idx;
991
992         muse_module_cmd_dispatchfunc *cmd_dispatcher = NULL;
993
994         LOGW("Enter");
995
996         muse_server = g_new0(muse_server_t, 1);
997
998         for (idx = 1; argv[idx] != NULL; idx++) {
999                 if (strcmp(argv[idx], "-D") == 0) {
1000                         LOGI("enable daemonize");
1001                         muse_server->daemonize = TRUE;
1002                 }
1003         }
1004
1005         ms_setup_syslog();
1006
1007         if (muse_server->daemonize)
1008                 _ms_daemonize();
1009         else
1010                 _ms_launch_foreground();
1011
1012         muse_server->boost.is_boosted = muse_boosting_start();
1013
1014 #ifdef MUSE_VIP_REGISTERED
1015         proc_stat_set_vip_process();
1016 #endif
1017
1018 #ifdef MUSE_TTRACE_LOG
1019         trace_end();
1020 #endif
1021
1022         ms_system_subscribe_external_event(muse_server->system);
1023
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);
1028                 return;
1029         }
1030 #endif
1031
1032         ms_gst_init(argv);
1033
1034         ms_init_bufmgr();
1035
1036 #ifdef MUSE_TTRACE_LOG
1037         trace_begin("MUSE:preloading module");
1038 #endif
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);
1044                 }
1045         }
1046 #ifdef MUSE_TTRACE_LOG
1047         trace_end();
1048 #endif
1049
1050 #ifdef MUSE_TTRACE_LOG
1051         trace_begin("MUSE:preloading GST module");
1052 #endif
1053         ms_gst_preload_plugin();
1054 #ifdef MUSE_TTRACE_LOG
1055         trace_end();
1056 #endif
1057
1058 #ifdef MUSE_GCOV_TEST
1059         muse_core_setenv("GCOV_PREFIX", "/tmp", 1);
1060 #endif
1061
1062         if (muse_server->boost.is_boosted)
1063                 muse_server->boost.is_boosted = !muse_boosting_stop();
1064
1065         muse_server->boost.is_inheritance_registered = muse_boosting_register_cpu_inheritance();
1066
1067         LOGW("Leave");
1068 }
1069
1070 muse_server_h ms_get_instance(void)
1071 {
1072         return muse_server;
1073 }
1074
1075 gboolean ms_check_module_idx(int idx)
1076 {
1077         int module_cnt = ms_config_get_host_cnt();
1078
1079         if (idx < 0 || idx >= module_cnt) {
1080                 LOGE("%d error - the number of modules is %d", idx, module_cnt);
1081                 return FALSE;
1082         }
1083
1084         return TRUE;
1085 }
1086
1087 ms_module_t *ms_get_module_instance(int idx)
1088 {
1089         muse_return_val_if_fail(ms_check_module_idx(idx), NULL);
1090
1091         return muse_server->module[idx];
1092 }
1093
1094 int ms_deinit(void)
1095 {
1096         int retval = MUSE_ERR;
1097         int idx;
1098
1099         LOGD("Enter");
1100
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);
1107
1108         ms_recursive_rmdir(MUSE_DATA_ROOT_PATH);
1109
1110         ms_set_state(MUSE_SERVER_STATE_IDLE);
1111
1112         if (muse_server->boost.is_inheritance_registered)
1113                 muse_server->boost.is_inheritance_registered = !muse_boosting_unregister_cpu_inheritance();
1114
1115         _ms_diag_deinit();
1116
1117 #ifdef MUSE_USE_WATCHDOG
1118         ms_watchdog_detach(muse_server->watchdog);
1119
1120         if (ms_watchdog_deinit(muse_server->watchdog) == MM_ERROR_NONE)
1121                 free(muse_server->watchdog);
1122         else
1123                 LOGE("Fail to deinitialize server watchdog");
1124 #endif
1125
1126         ms_remove_ready_file();
1127
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]);
1134         }
1135
1136         if (remove(MUSE_DEFAULT_PIDFILE) == -1)
1137                 LOGE("remove %s failed [errno : %d]", MUSE_DEFAULT_PIDFILE, errno);
1138
1139         for (idx = 0; idx < muse_server->conf->host_cnt; idx++)
1140                 ms_module_deinit(muse_server->module[idx]);
1141
1142         ms_security_deinit(muse_server->security);
1143         muse_server->security = NULL;
1144
1145         ms_system_deinit(muse_server->system);
1146         muse_server->system = NULL;
1147
1148         ms_log_deinit(muse_server->log);
1149         muse_server->log = NULL;
1150
1151         ms_config_deinit(muse_server->conf);
1152         muse_server->conf = NULL;
1153
1154         ms_connection_deinit(muse_server->connection);
1155         muse_server->connection = NULL;
1156
1157         muse_core_destroy_fd_table();
1158
1159         ms_deinit_bufmgr();
1160
1161         g_mutex_clear(&muse_server->state_lock);
1162
1163         g_free(muse_server);
1164         muse_server = NULL;
1165
1166         LOGD("Leave");
1167         return retval;
1168 }
1169
1170 void ms_check_cpu_memory(void)
1171 {
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;
1176
1177         muse_return_if_fail(muse_server);
1178
1179         connection = muse_server->connection;
1180         muse_return_if_fail(connection);
1181
1182         system = muse_server->system;
1183         muse_return_if_fail(system);
1184
1185         ms_connection_lock(connection);
1186
1187         if (g_queue_is_empty(connection->instance_q)) {
1188                 used_pss = ms_system_get_memory_usage(muse_server->pid);
1189                 cpu_usage = muse_core_get_process_cpu_usage(muse_server->pid);
1190
1191                 LOGW("[%d] Proportional set size %d (KByte) (CPU %d %%)", muse_server->pid, used_pss, cpu_usage);
1192
1193                 memory_threshold = ms_config_get_memory_threshold();
1194                 cpu_threshold = ms_config_get_cpu_threshold();
1195
1196                 if (used_pss >= memory_threshold) {
1197                         ms_log_process_info(muse_server->pid);
1198
1199                         snprintf(err_msg, sizeof(err_msg), "[Memory Leak] %d >= %d (KByte)", used_pss, memory_threshold);
1200
1201                         LOGE("%s", err_msg);
1202                         ms_connection_unlock(connection);
1203                         ms_terminate(SIGTERM);
1204                 }
1205
1206                 if (cpu_usage > cpu_threshold)
1207                         ms_system_stat_attach(system);
1208
1209                 muse_core_remove_all_fd_table();
1210         } else {
1211                 LOGI("skip cpu memory check due to instance queue length : %d", g_queue_get_length(connection->instance_q));
1212         }
1213
1214         ms_connection_unlock(connection);
1215 }
1216
1217 void ms_check_stdin_close(void)
1218 {
1219         ms_connection_t *connection = muse_server->connection;
1220         muse_return_if_fail(connection);
1221
1222         ms_connection_lock(connection);
1223
1224         if (fcntl(STDIN_FILENO, F_GETFD) == -1 && errno == EBADF)
1225                 LOGE("stdin is closed.");
1226
1227         ms_connection_unlock(connection);
1228 }
1229
1230 void ms_new(void)
1231 {
1232         int fd[MUSE_CHANNEL_MAX];
1233         int i, j;
1234
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;
1238                 else
1239                         fd[i] = _ms_new(i);
1240
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++)
1244                                 close(fd[j]);
1245                         return;
1246                 }
1247         }
1248
1249         _ms_create_new_server_from_fd(fd, READ | PERSIST);
1250 }
1251
1252 void ms_run(void)
1253 {
1254         LOGW("Enter");
1255
1256         muse_return_if_fail(muse_server->main_loop);
1257
1258         muse_return_if_fail(g_idle_add_full(G_PRIORITY_HIGH, _ms_idle_cb, NULL, NULL) > 0);
1259
1260         LOGI("g_main_loop_run");
1261         g_main_loop_run(muse_server->main_loop);
1262
1263         LOGW("Leave");
1264 }
1265
1266 void ms_cmd_dispatch(muse_module_h m, muse_module_command_e cmd)
1267 {
1268         muse_module_cmd_dispatchfunc *cmd_dispatcher = NULL;
1269
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);
1274         }
1275 }
1276
1277 void ms_terminate(int signo)
1278 {
1279         muse_return_if_fail(muse_server);
1280
1281         ms_set_state(MUSE_SERVER_STATE_IDLE);
1282
1283         LOGE("send signal %d to process %d", signo, muse_server->pid);
1284         raise(signo);
1285 }
1286
1287 int ms_get_pid(muse_module_h m)
1288 {
1289         muse_return_val_if_fail(m, MUSE_ERR);
1290         return m->pid;
1291 }
1292
1293 void ms_log_process_info(int pid)
1294 {
1295         muse_core_log_process_thread_info(pid);
1296
1297         muse_core_log_process_opened_fds(pid);
1298
1299         muse_core_log_process_cpu_memory(pid);
1300 }
1301
1302 void ms_log_user_group_info(void)
1303 {
1304         uid_t uid;
1305         gid_t gid;
1306         char buffer[MUSE_MSG_MAX_LENGTH];
1307         struct passwd pwbuf;
1308         struct passwd *pwbufp;
1309         struct group gbuf;
1310         struct group *gbufp;
1311
1312         uid = getuid();
1313         gid = getgid();
1314
1315         getpwuid_r(uid, &pwbuf, buffer, sizeof(buffer), &pwbufp);
1316         muse_return_if_fail(pwbufp);
1317
1318         getgrgid_r(gid, &gbuf, buffer, sizeof(buffer), &gbufp);
1319         muse_return_if_fail(gbufp);
1320
1321         LOGE("user [%s : %lu] group [%s : %lu]", pwbufp->pw_name, (unsigned long)uid, gbufp->gr_name, (unsigned long)gid);
1322 }
1323
1324 gboolean ms_is_log_enabled(void)
1325 {
1326         return ms_config_is_log_enabled();
1327 }
1328
1329 gboolean ms_init_bufmgr(void)
1330 {
1331         LOGD("Enter");
1332
1333         muse_return_val_if_fail(muse_server, FALSE);
1334
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();
1339                 return FALSE;
1340         }
1341
1342         LOGD("Leave bufmgr: %p", muse_server->bufmgr);
1343
1344         return TRUE;
1345 }
1346
1347 void ms_deinit_bufmgr(void)
1348 {
1349         LOGD("Enter");
1350
1351         muse_return_if_fail(muse_server);
1352         muse_return_if_fail(muse_server->bufmgr);
1353
1354         tbm_bufmgr_deinit(muse_server->bufmgr);
1355
1356         LOGD("Leave");
1357 }
1358
1359 void ms_cmd_dispatch_foreach_func(gpointer data, gpointer user_data)
1360 {
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;
1365
1366         muse_return_if_fail(muse_server);
1367         muse_return_if_fail(m);
1368         muse_return_if_fail(dispatch);
1369
1370         cmd = dispatch->cmd;
1371
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);
1376         }
1377
1378         ms_cmd_dispatch(m, cmd);
1379         SECURE_LOGI("[%s] module %p (%s)", module_cmd[cmd], m, muse_server->conf->host[m->idx]);
1380
1381         if (cmd == MUSE_MODULE_COMMAND_EXTERNAL_STORAGE_STATE_CHANGED)
1382                 muse_server_set_user_data(m, NULL);
1383 }
1384
1385 void ms_set_state(ms_state_e state)
1386 {
1387         muse_return_if_fail(muse_server);
1388
1389         g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&muse_server->state_lock);
1390
1391         muse_server->state = state;
1392 }
1393
1394 gboolean ms_is_server_ready(void)
1395 {
1396         muse_return_val_if_fail(muse_server, FALSE);
1397
1398         g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&muse_server->state_lock);
1399
1400         return muse_server->state == MUSE_SERVER_STATE_READY;
1401 }
1402
1403 gboolean ms_create_ready_file(void)
1404 {
1405         LOGD("Enter");
1406 #ifndef MUSE_USE_LWIPC
1407         int ready_fd;
1408 #endif
1409
1410 #ifdef MUSE_USE_LWIPC
1411         _ms_wait_event();
1412
1413         ms_set_state(MUSE_SERVER_STATE_READY);
1414
1415         if (LwipcEventDone(MUSE_SERVER_READY) < 0) {
1416                 LOGE("Fail to send server ready done event");
1417                 return FALSE;
1418         }
1419 #else
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);
1423
1424                 close(ready_fd);
1425                 ms_set_state(MUSE_SERVER_STATE_READY);
1426         } else {
1427                 LOGE("[%d] Fail to create MUSE_SERVER_READY(%s)", ready_fd, MUSE_SERVER_READY);
1428                 return FALSE;
1429         }
1430 #endif
1431         LOGD("Leave");
1432
1433         return TRUE;
1434
1435 }
1436
1437 void ms_remove_ready_file(void)
1438 {
1439 #ifdef MUSE_USE_LWIPC
1440         LwipcResetEvent(MUSE_SERVER_READY);
1441 #else
1442         unlink(MUSE_SERVER_READY);
1443         unlink(MUSE_DEFAULT_PIDFILE);
1444 #endif
1445 }
1446
1447 const char *ms_get_command_string(int cmd)
1448 {
1449         if (cmd == API_CREATE)
1450                 return "connect";
1451         else if (cmd == API_DESTROY)
1452                 return "disconnect";
1453         else
1454                 LOGE("Invalid value of cmd (%d)", cmd);
1455
1456         return "Invalid value of cmd";
1457 }
1458
1459 gboolean ms_module_idx_is_valid(muse_module_h m)
1460 {
1461         return (m->idx >= 0 && m->idx < ms_config_get_host_cnt());
1462 }