Add to check pid from __accept_candidate_process()
[platform/core/appfw/launchpad.git] / src / launchpad / src / launchpad.c
1 /*
2  * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #define _GNU_SOURCE
18 #include <errno.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <systemd/sd-daemon.h>
22 #include <sys/prctl.h>
23 #include <sys/socket.h>
24 #include <sys/un.h>
25 #include <sys/types.h>
26 #include <sys/wait.h>
27 #include <sys/stat.h>
28 #include <sys/capability.h>
29 #include <sched.h>
30 #include <stdbool.h>
31 #include <malloc.h>
32 #include <bundle_internal.h>
33 #include <security-manager.h>
34 #include <time.h>
35 #include <systemd/sd-daemon.h>
36 #include <glib.h>
37 #include <linux/limits.h>
38 #include <ttrace.h>
39 #include <vconf.h>
40 #include <math.h>
41 #include <trust-anchor.h>
42
43 #include "key.h"
44 #include "launcher_info.h"
45 #include "launchpad_common.h"
46 #include "launchpad_config.h"
47 #include "launchpad_dbus.h"
48 #include "launchpad_debug.h"
49 #include "launchpad_inotify.h"
50 #include "launchpad_io_channel.h"
51 #include "launchpad_log.h"
52 #include "launchpad_memory_monitor.h"
53 #include "launchpad_plugin.h"
54 #include "launchpad_proc.h"
55 #include "launchpad_signal.h"
56 #include "launchpad_types.h"
57 #include "loader_info.h"
58 #include "perf.h"
59
60 #define AUL_PR_NAME         16
61 #define EXEC_CANDIDATE_EXPIRED 5
62 #define EXEC_CANDIDATE_WAIT 1
63 #define DIFF(a, b) (((a) > (b)) ? (a) - (b) : (b) - (a))
64 #define CANDIDATE_NONE 0
65 #define HYDRA_NONE 0
66 #define PROCESS_POOL_LAUNCHPAD_SOCK ".launchpad-process-pool-sock"
67 #define LAUNCHPAD_LOGGER_SOCK ".launchpad-logger-sock"
68 #define LOADER_PATH_DEFAULT "/usr/bin/launchpad-loader"
69 #define LOADER_INFO_PATH        "/usr/share/aul"
70 #define OPT_SHARE_PATH "/opt/share"
71 #define LOADERS_PATH "loaders"
72 #define APP_DEFINED_LOADER_INFO_PATH    OPT_SHARE_PATH "/" LOADERS_PATH
73 #define COMMON_LOADER_NAME "common-loader1"
74
75 #define LAUNCHER_INFO_PATH      LOADER_INFO_PATH
76 #define REGULAR_UID_MIN 5000
77 #define PAD_ERR_FAILED                  -1
78 #define PAD_ERR_REJECTED                -2
79 #define PAD_ERR_INVALID_ARGUMENT        -3
80 #define PAD_ERR_INVALID_PATH            -4
81 #define CPU_CHECKER_TIMEOUT             1000
82 #define PI                              3.14159265
83 #define WIN_SCORE 100
84 #define LOSE_SCORE_RATE 0.7f
85
86 enum candidate_process_state_e {
87         CANDIDATE_PROCESS_STATE_RUNNING,
88         CANDIDATE_PROCESS_STATE_PAUSED,
89 };
90
91 typedef struct {
92         int type;
93         bool prepared;
94         int pid; /* for hydra this pid is not the pid of hydra itself */
95                  /* but pid of non-hydra candidate, which was forked from hydra */
96         int hydra_pid;
97         int loader_id;
98         int caller_pid;
99         int send_fd;
100         int hydra_fd;
101         int last_exec_time;
102         guint timer;
103         char *loader_name;
104         char *loader_path;
105         char *loader_extra;
106         int detection_method;
107         int timeout_val;
108         unsigned long long cpu_total_time;
109         unsigned long long cpu_idle_time;
110         int threshold;
111         int threshold_max;
112         int threshold_min;
113         int cur_event;
114         bool on_boot;
115         bool app_exists;
116         bool touched;
117         int activation_method;
118         int deactivation_method;
119         unsigned int ttl;
120         guint live_timer;
121         int state;
122         bool is_hydra;
123         bool app_check;
124         io_channel_h client_channel;
125         io_channel_h channel;
126         io_channel_h hydra_channel;
127         unsigned int score;
128         unsigned int pss;
129         int cpu_check_count;
130 } candidate_process_context_t;
131
132 typedef struct {
133         GPollFD *gpollfd;
134         int type;
135         int loader_id;
136 } loader_context_t;
137
138 typedef struct {
139         GQueue *queue;
140         guint timer;
141         guint idle_checker;
142         candidate_process_context_t *running_cpc;
143 } sequencer;
144
145 struct app_launch_arg {
146         const char *appid;
147         const char *app_path;
148         appinfo_t *menu_info;
149         bundle *kb;
150 };
151
152 struct app_arg {
153         int argc;
154         char **argv;
155 };
156
157 struct app_info {
158         const char *type;
159         bool exists;
160 };
161
162 static int __sys_hwacc;
163 static GList *loader_info_list;
164 static GList *app_defined_loader_info_list;
165 static int user_slot_offset;
166 static GList *candidate_slot_list;
167 static app_labels_monitor *label_monitor;
168 static GList *launcher_info_list;
169 static GHashTable *__pid_table;
170 static int __memory_status_low;
171 static int __memory_status_normal;
172 static sequencer __sequencer;
173 static int MEMORY_STATUS_LOW;
174 static int MEMORY_STATUS_NORMAL;
175 static int MAX_CPU_CHECK_COUNT;
176
177 static io_channel_h __logger_channel;
178 static io_channel_h __label_monitor_channel;
179 static io_channel_h __launchpad_channel;
180
181 static candidate_process_context_t *__add_slot(int type, int loader_id,
182                 int caller_pid, const char *loader_name,
183                 const char *loader_path, const char *extra,
184                 int detection_method, int activation_method,
185                 int deactivation_method, unsigned int ttl, int timeout_val,
186                 int threshold_max, int threshold_min, bool on_boot,
187                 bool app_exists, bool is_hydra, bool app_check);
188 static int __remove_slot(int type, int loader_id);
189 static int __add_default_slots(void);
190 static gboolean __handle_idle_checker(gpointer data);
191 static int __add_idle_checker(int detection_method, GList *cur);
192 static void __dispose_candidate_process(candidate_process_context_t *cpc);
193 static bool __is_low_memory(void);
194 static void __update_slot_state(candidate_process_context_t *cpc, int method,
195                 bool force);
196 static void __init_app_defined_loader_monitor(void);
197 static gboolean __launchpad_recovery_cb(gpointer data);
198 static gboolean __logger_recovery_cb(gpointer data);
199
200 static gboolean __handle_queuing_slots(gpointer data)
201 {
202         candidate_process_context_t *cpc;
203         unsigned long long total = 0;
204         unsigned long long idle = 0;
205
206         if (__sequencer.idle_checker > 0)
207                 return G_SOURCE_CONTINUE;
208
209         if (g_queue_is_empty(__sequencer.queue)) {
210                 __sequencer.timer = 0;
211                 return G_SOURCE_REMOVE;
212         }
213
214         cpc = (candidate_process_context_t *)g_queue_pop_head(
215                         __sequencer.queue);
216         if (!cpc) {
217                 _E("Critical error!");
218                 __sequencer.timer = 0;
219                 return G_SOURCE_REMOVE;;
220         }
221
222         if (cpc->app_check && !cpc->app_exists) {
223                 _W("The application is not installed. Type(%d)", cpc->type);
224                 return G_SOURCE_CONTINUE;
225         }
226
227         if (cpc->timer) {
228                 g_source_remove(cpc->timer);
229                 cpc->timer = 0;
230         }
231
232         if (cpc->pid != CANDIDATE_NONE) {
233                 _W("The slot(%d) is already running. pid(%d)",
234                                 cpc->type, cpc->pid);
235                 return G_SOURCE_CONTINUE;
236         }
237
238         _get_cpu_idle(&total, &idle);
239         cpc->cpu_idle_time = idle;
240         cpc->cpu_total_time = total;
241         cpc->cpu_check_count = 0;
242
243         __sequencer.idle_checker = g_timeout_add(CPU_CHECKER_TIMEOUT,
244                         __handle_idle_checker, cpc);
245         __sequencer.running_cpc = cpc;
246
247         _D("[__SEQUENCER__] Add idle checker. Type(%d)", cpc->type);
248
249         return G_SOURCE_CONTINUE;
250 }
251
252 static bool __sequencer_slot_is_running(candidate_process_context_t *cpc)
253 {
254         if (__sequencer.running_cpc == cpc)
255                 return true;
256
257         return false;
258 }
259
260 static bool __sequencer_slot_exist(candidate_process_context_t *cpc)
261 {
262         GList *found;
263
264         found = g_queue_find(__sequencer.queue, cpc);
265         if (found)
266                 return true;
267
268         return false;
269 }
270
271 static int __sequencer_add_slot(candidate_process_context_t *cpc)
272 {
273         if (__sequencer_slot_exist(cpc)) {
274                 _W("Already exists");
275                 return -1;
276         }
277
278         if (__sequencer_slot_is_running(cpc)) {
279                 _W("slot(%d) is running", cpc->type);
280                 return -1;
281         }
282
283         g_queue_push_tail(__sequencer.queue, cpc);
284
285         return 0;
286 }
287
288 static void __sequencer_remove_slot(candidate_process_context_t *cpc)
289 {
290         g_queue_remove(__sequencer.queue, cpc);
291 }
292
293 static void __sequencer_run(void)
294 {
295         if (__sequencer.timer)
296                 return;
297
298         __sequencer.timer = g_timeout_add(500, __handle_queuing_slots, NULL);
299         if (!__sequencer.timer)
300                 _E("Failed to add sequencer timer");
301 }
302
303 static void __sequencer_stop(void)
304 {
305         if (!__sequencer.timer)
306                 return;
307
308         g_source_remove(__sequencer.timer);
309         __sequencer.timer = 0;
310 }
311
312 static bool __sequencer_queue_is_empty(void)
313 {
314         if (g_queue_is_empty(__sequencer.queue))
315                 return true;
316
317         return false;
318 }
319
320 static int __sequencer_init(void)
321 {
322         _D("[__SEQUENCER__] Init");
323
324         __sequencer.queue = g_queue_new();
325         if (!__sequencer.queue) {
326                 _E("Out of memory");
327                 return -1;
328         }
329
330         return 0;
331 }
332
333 static void __sequencer_fini(void)
334 {
335         _D("[__SEQUENCER__] Finish");
336
337         if (__sequencer.idle_checker > 0)
338                 g_source_remove(__sequencer.idle_checker);
339
340         if (__sequencer.timer > 0)
341                 g_source_remove(__sequencer.timer);
342
343         g_queue_free(__sequencer.queue);
344 }
345
346 static int __make_loader_id(void)
347 {
348         static int id = PAD_LOADER_ID_DYNAMIC_BASE;
349
350         return ++id;
351 }
352
353 static candidate_process_context_t *__find_slot_from_static_type(int type)
354 {
355         candidate_process_context_t *cpc;
356         GList *iter = candidate_slot_list;
357
358         if (type == LAUNCHPAD_LOADER_TYPE_DYNAMIC ||
359                         type == LAUNCHPAD_LOADER_TYPE_UNSUPPORTED)
360                 return NULL;
361
362         while (iter) {
363                 cpc = (candidate_process_context_t *)iter->data;
364                 if (type == cpc->type)
365                         return cpc;
366
367                 iter = g_list_next(iter);
368         }
369
370         return NULL;
371 }
372
373 static candidate_process_context_t *__find_slot_from_pid(int pid)
374 {
375         candidate_process_context_t *cpc;
376         GList *iter = candidate_slot_list;
377
378         while (iter) {
379                 cpc = (candidate_process_context_t *)iter->data;
380                 if (pid == cpc->pid)
381                         return cpc;
382
383                 iter = g_list_next(iter);
384         }
385
386         return NULL;
387 }
388
389 static candidate_process_context_t *__find_hydra_slot_from_pid(int pid)
390 {
391         candidate_process_context_t *cpc;
392         GList *iter = candidate_slot_list;
393
394         while (iter) {
395                 cpc = (candidate_process_context_t *)iter->data;
396                 if (cpc->is_hydra && pid == cpc->hydra_pid)
397                         return cpc;
398
399                 iter = g_list_next(iter);
400         }
401
402         return NULL;
403 }
404
405 static candidate_process_context_t *__find_slot_from_caller_pid(int caller_pid)
406 {
407         candidate_process_context_t *cpc;
408         GList *iter = candidate_slot_list;
409
410         while (iter) {
411                 cpc = (candidate_process_context_t *)iter->data;
412                 if (caller_pid == cpc->caller_pid)
413                         return cpc;
414
415                 iter = g_list_next(iter);
416         }
417
418         return NULL;
419 }
420
421 static candidate_process_context_t *__find_slot_from_loader_id(int id)
422 {
423         candidate_process_context_t *cpc;
424         GList *iter = candidate_slot_list;
425
426         while (iter) {
427                 cpc = (candidate_process_context_t *)iter->data;
428                 if (id == cpc->loader_id)
429                         return cpc;
430
431                 iter = g_list_next(iter);
432         }
433
434         return NULL;
435 }
436
437 static candidate_process_context_t *__find_slot_from_loader_name(const char *loader_name)
438 {
439         candidate_process_context_t *cpc;
440         GList *iter = candidate_slot_list;
441
442         while (iter) {
443                 cpc = (candidate_process_context_t *)iter->data;
444                 if (strcmp(cpc->loader_name, loader_name) == 0)
445                         return cpc;
446
447                 iter = g_list_next(iter);
448         }
449
450         return NULL;
451 }
452
453 static candidate_process_context_t *__find_slot(int type, int loader_id)
454 {
455         if (type == LAUNCHPAD_LOADER_TYPE_DYNAMIC)
456                 return __find_slot_from_loader_id(loader_id);
457
458         return __find_slot_from_static_type(type);
459 }
460
461 static void __update_slot_score(candidate_process_context_t *slot)
462 {
463         if (!slot)
464                 return;
465
466         slot->score *= LOSE_SCORE_RATE;
467         slot->score += WIN_SCORE;
468 }
469
470 static void __update_slots_pss(void)
471 {
472         candidate_process_context_t *cpc;
473         GList *iter;
474
475         iter = candidate_slot_list;
476         while (iter) {
477                 cpc = (candidate_process_context_t *)iter->data;
478                 iter = g_list_next(iter);
479
480                 if (cpc->pid == CANDIDATE_NONE)
481                         continue;
482
483                 _proc_get_mem_pss(cpc->pid, &cpc->pss);
484         }
485 }
486
487 static gint __compare_slot(gconstpointer a, gconstpointer b)
488 {
489         candidate_process_context_t *slot_a = (candidate_process_context_t *)a;
490         candidate_process_context_t *slot_b = (candidate_process_context_t *)b;
491
492         if (slot_a->is_hydra && !slot_b->is_hydra)
493                 return -1;
494         if (!slot_a->is_hydra && slot_b->is_hydra)
495                 return 1;
496
497         if (slot_a->score < slot_b->score)
498                 return 1;
499         if (slot_a->score > slot_b->score)
500                 return -1;
501
502         if (slot_a->pss < slot_b->pss)
503                 return -1;
504         if (slot_a->pss > slot_b->pss)
505                 return 1;
506
507         return 0;
508 }
509
510 static candidate_process_context_t *__get_running_slot(bool is_hydra)
511 {
512         candidate_process_context_t *cpc;
513         GList *iter;
514
515         iter = candidate_slot_list;
516         while (iter) {
517                 cpc = (candidate_process_context_t *)iter->data;
518                 if (cpc->is_hydra == is_hydra && cpc->pid != CANDIDATE_NONE)
519                         return cpc;
520
521                 iter = g_list_next(iter);
522         }
523
524         return NULL;
525 }
526
527 static void __pause_last_running_slot(bool is_hydra)
528 {
529         candidate_process_context_t *cpc = NULL;
530         GList *iter;
531
532         iter = g_list_last(candidate_slot_list);
533         while (iter) {
534                 cpc = (candidate_process_context_t *)iter->data;
535                 if (cpc->is_hydra == is_hydra && cpc->pid != CANDIDATE_NONE)
536                         break;
537
538                 iter = g_list_previous(iter);
539         }
540
541         if (!cpc)
542                 return;
543
544         __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, true);
545 }
546
547 static void __resume_all_slots(void)
548 {
549         candidate_process_context_t *cpc;
550         GList *iter;
551
552         iter = candidate_slot_list;
553         while (iter) {
554                 cpc = (candidate_process_context_t *)iter->data;
555                 __update_slot_state(cpc, METHOD_AVAILABLE_MEMORY, false);
556
557                 iter = g_list_next(iter);
558         }
559 }
560
561 static void __kill_process(int pid)
562 {
563         char err_str[MAX_LOCAL_BUFSZ] = { 0, };
564
565         if (kill(pid, SIGKILL) == -1) {
566                 _E("send SIGKILL: %s",
567                                 strerror_r(errno, err_str, sizeof(err_str)));
568         }
569 }
570
571 static void __refuse_candidate_process(int server_fd)
572 {
573         int client_fd = -1;
574
575         if (server_fd == -1) {
576                 _E("arguments error!");
577                 goto error;
578         }
579
580         client_fd = accept(server_fd, NULL, NULL);
581         if (client_fd == -1) {
582                 _E("accept error!");
583                 goto error;
584         }
585
586         close(client_fd);
587         _D("refuse connection!");
588
589 error:
590         return;
591 }
592
593 static int __accept_candidate_process(int server_fd, int *out_client_fd,
594                 int *out_client_pid, int cpc_pid)
595 {
596         int client_fd = -1;
597         int recv_pid = 0;
598         int ret;
599         socklen_t len;
600         struct ucred cred = {};
601
602         if (server_fd == -1 || out_client_fd == NULL ||
603                         out_client_pid == NULL) {
604                 _E("arguments error!");
605                 goto error;
606         }
607
608         client_fd = accept(server_fd, NULL, NULL);
609         if (client_fd == -1) {
610                 _E("accept error!");
611                 goto error;
612         }
613
614         if (_set_sock_option(client_fd, 1) < 0) {
615                 _E("Failed to set sock option");
616                 goto error;
617         }
618
619         ret = recv(client_fd, &recv_pid, sizeof(recv_pid), MSG_WAITALL);
620         if (ret == -1) {
621                 _E("recv error!");
622                 goto error;
623         }
624
625         len = sizeof(cred);
626         ret = getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED, &cred, &len);
627         if (ret < 0) {
628                 _E("getsockopt error");
629                 goto error;
630         }
631
632         if (cred.pid != cpc_pid) {
633                 _E("Invalid accept. pid(%d)", cred.pid);
634                 goto error;
635         }
636
637         if (cred.pid != recv_pid)
638                 _W("Not equal recv and real pid");
639
640         *out_client_fd = client_fd;
641         *out_client_pid = cred.pid;
642
643         return *out_client_fd;
644
645 error:
646         if (client_fd != -1)
647                 close(client_fd);
648
649         return -1;
650 }
651
652 static int __listen_addr(struct sockaddr_un *addr)
653 {
654         int fd = -1;
655         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
656         if (fd < 0) {
657                 _E("Socket error");
658                 goto error;
659         }
660
661         unlink(addr->sun_path);
662
663         _D("bind to %s", addr->sun_path);
664         if (bind(fd, (struct sockaddr *)addr, sizeof(struct sockaddr_un)) < 0) {
665                 _E("bind error");
666                 goto error;
667         }
668
669         _D("listen to %s", addr->sun_path);
670         if (listen(fd, MAX_PENDING_CONNECTIONS) == -1) {
671                 _E("listen error");
672                 goto error;
673         }
674
675         SECURE_LOGD("[launchpad] done, listen fd: %d", fd);
676         return fd;
677
678 error:
679         if (fd != -1)
680                 close(fd);
681
682         return -1;
683 }
684
685 static int __listen_candidate_process(int type, int loader_id)
686 {
687         struct sockaddr_un addr;
688
689         _D("[launchpad] enter, type: %d", type);
690
691         memset(&addr, 0x00, sizeof(struct sockaddr_un));
692         addr.sun_family = AF_UNIX;
693         snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/daemons/%u/%s%d-%d",
694                         SOCKET_PATH, getuid(), LAUNCHPAD_LOADER_SOCKET_NAME,
695                         type, loader_id);
696
697         return __listen_addr(&addr);
698 }
699
700 static int __listen_hydra_process(int type, int loader_id)
701 {
702         struct sockaddr_un addr;
703
704         _D("[launchpad] enter, type: %d", type);
705
706         memset(&addr, 0x00, sizeof(struct sockaddr_un));
707         addr.sun_family = AF_UNIX;
708         snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/daemons/%d/%s%d-%d",
709                         SOCKET_PATH, getuid(), HYDRA_LOADER_SOCKET_NAME,
710                         type, loader_id);
711
712         return __listen_addr(&addr);
713 }
714
715 static int __get_loader_id(bundle *kb)
716 {
717         const char *val;
718
719         val = bundle_get_val(kb, AUL_K_LOADER_ID);
720         if (val == NULL)
721                 return -1;
722         _W("Requested loader id: %s", val);
723
724         return atoi(val);
725 }
726
727 static int __candidate_process_real_launch(int candidate_fd, app_pkt_t *pkt)
728 {
729         return _send_pkt_raw(candidate_fd, pkt);
730 }
731
732 static int __real_send(int clifd, int ret)
733 {
734         if (clifd < 3) {
735                 _E("Invalid parameter. clifd(%d)", clifd);
736                 return -1;
737         }
738
739         if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
740                 if (errno == EPIPE) {
741                         _E("send failed due to EPIPE.");
742                         close(clifd);
743                         return -1;
744                 }
745                 _E("send fail to client");
746         }
747
748         close(clifd);
749         return 0;
750 }
751
752 static void __send_result_to_caller(int clifd, int ret, const char *app_path)
753 {
754         _W("send result: %d", ret);
755
756         if (clifd == -1)
757                 return;
758
759         if (ret <= 1) {
760                 _E("launching failed");
761                 __real_send(clifd, ret);
762                 return;
763         }
764
765         if (__real_send(clifd, ret) < 0)
766                 __kill_process(ret);
767 }
768
769 static int __fork_app_process(int (*child_fn)(void *), void *arg)
770 {
771         int pid;
772         int ret;
773
774         pid = fork();
775
776         if (pid == -1) {
777                 _E("failed to fork child process");
778                 return -1;
779         }
780
781         if (pid == 0) {
782                 _W("security_manager_prepare_app_candidate ++");
783                 ret = security_manager_prepare_app_candidate();
784                 _W("security_manager_prepare_app_candidate --");
785                 if (ret != SECURITY_MANAGER_SUCCESS) {
786                         _E("failed to prepare app candidate process (%d)", ret);
787                         exit(1);
788                 }
789
790                 ret = child_fn(arg);
791                 _E("failed to exec app process (%d)", errno);
792                 exit(ret);
793         }
794
795         return pid;
796 }
797
798 static int __exec_loader_process(void *arg)
799 {
800         char **argv = arg;
801         char err_buf[1024];
802
803         _send_cmd_to_amd(LAUNCHPAD_CHILD_PROCESS);
804         _signal_unblock_sigchld();
805         _close_all_fds();
806         _setup_stdio(basename(argv[LOADER_ARG_PATH]));
807
808         if (execv(argv[LOADER_ARG_PATH], argv) < 0) {
809                 _send_message_to_logger(argv[LOADER_ARG_PATH],
810                         "Failed to prepare candidate process. error(%d:%s)",
811                         errno, strerror_r(errno, err_buf, sizeof(err_buf)));
812         } else {
813                 _D("Succeeded to prepare candidate_process");
814         }
815
816         return -1;
817 }
818
819 static gboolean __handle_deactivate_event(gpointer user_data)
820 {
821         candidate_process_context_t *cpc;
822
823         cpc = (candidate_process_context_t *)user_data;
824         __update_slot_state(cpc, METHOD_TTL, false);
825         _D("Deactivate event: type(%d)", cpc->type);
826
827         return G_SOURCE_REMOVE;
828 }
829
830 static void __set_live_timer(candidate_process_context_t *cpc)
831 {
832         if (!cpc)
833                 return;
834
835         if (cpc->deactivation_method & METHOD_TTL) {
836                 if (cpc->live_timer == 0) {
837                         cpc->live_timer = g_timeout_add_seconds(cpc->ttl,
838                                         __handle_deactivate_event, cpc);
839                 }
840         }
841 }
842
843 static int __hydra_send_request(int fd, enum hydra_cmd cmd)
844 {
845         int sent = 0;
846         int size = sizeof(cmd);
847         int send_ret = 0;
848
849         while (sent != size) {
850                 send_ret = send(fd, (char *)&cmd + sent,
851                                 size - sent, MSG_NOSIGNAL);
852                 if (send_ret == -1) {
853                         _E("send error! (%d)", errno);
854                         return -1;
855                 }
856
857                 sent += send_ret;
858                 _D("send(%d: ret: %d) : %d / %d",
859                         fd, send_ret, sent, size);
860         }
861
862         return 0;
863 }
864
865 static int __hydra_send_launch_candidate_request(int fd)
866 {
867         SECURE_LOGD("Send launch cmd to hydra, fd: %d", fd);
868         return __hydra_send_request(fd, LAUNCH_CANDIDATE);
869 }
870
871 static int __prepare_candidate_process(int type, int loader_id)
872 {
873         int pid;
874         char type_str[12] = {0, };
875         char loader_id_str[12] = {0, };
876         char argbuf[LOADER_ARG_LEN];
877         char *argv[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
878         candidate_process_context_t *cpt = __find_slot(type, loader_id);
879
880         if (cpt == NULL)
881                 return -1;
882
883         if (cpt->is_hydra && cpt->hydra_pid != HYDRA_NONE)
884                 return __hydra_send_launch_candidate_request(cpt->hydra_fd);
885
886         _D("prepare candidate process / type:%d", type);
887         memset(argbuf, ' ', LOADER_ARG_LEN);
888         argbuf[LOADER_ARG_LEN - 1] = '\0';
889         argv[LOADER_ARG_DUMMY] = argbuf;
890
891         cpt->last_exec_time = time(NULL);
892
893         snprintf(loader_id_str, sizeof(loader_id_str), "%d", loader_id);
894         snprintf(type_str, sizeof(type_str), "%d", type);
895         argv[LOADER_ARG_PATH] = cpt->loader_path;
896         argv[LOADER_ARG_TYPE] = type_str;
897         argv[LOADER_ARG_ID] = loader_id_str;
898         argv[LOADER_ARG_HYDRA] = cpt->is_hydra ? "1" : "0";
899         argv[LOADER_ARG_EXTRA] = cpt->loader_extra;
900
901         pid = __fork_app_process(__exec_loader_process, argv);
902         if (pid == -1) {
903                 _E("Failed to fork candidate_process");
904                 return -1;
905         }
906
907         if (cpt->is_hydra) {
908                 cpt->hydra_pid = pid;
909         } else {
910                 cpt->pid = pid;
911                 __set_live_timer(cpt);
912         }
913
914         _log_print("[CANDIDATE]", "pid(%7d) | type(%d) | loader(%s)",
915                 pid, cpt->loader_id, cpt->loader_name);
916         _memory_monitor_reset_timer();
917
918         return 0;
919 }
920
921 static gboolean __handle_timeout_event(gpointer user_data)
922 {
923         candidate_process_context_t *cpc;
924
925         cpc = (candidate_process_context_t *)user_data;
926         cpc->timer = 0;
927
928         if (cpc->pid != CANDIDATE_NONE) {
929                 _W("Candidate(%d) process(%d) is running", cpc->type, cpc->pid);
930                 return G_SOURCE_REMOVE;
931         }
932
933         __sequencer_add_slot(cpc);
934         __sequencer_run();
935         return G_SOURCE_REMOVE;
936 }
937
938 static void __set_timer(candidate_process_context_t *cpc)
939 {
940         if (cpc == NULL || cpc->timer > 0)
941                 return;
942
943         if ((cpc->detection_method & METHOD_TIMEOUT) &&
944                         cpc->state == CANDIDATE_PROCESS_STATE_RUNNING) {
945                 cpc->timer = g_timeout_add(cpc->timeout_val,
946                                 __handle_timeout_event, cpc);
947         }
948 }
949
950 static void __reset_slot(candidate_process_context_t *cpc)
951 {
952         if (cpc == NULL)
953                 return;
954
955         cpc->send_fd = -1;
956         cpc->prepared = false;
957         cpc->pid = CANDIDATE_NONE;
958         cpc->client_channel = NULL;
959         cpc->timer = 0;
960         cpc->live_timer = 0;
961 }
962
963 static void __dispose_candidate_process(candidate_process_context_t *cpc)
964 {
965         if (!cpc)
966                 return;
967
968         _D("Dispose candidate process %d", cpc->type);
969         if (cpc->pid > 0) {
970                 _D("kill process %d", cpc->pid);
971                 __kill_process(cpc->pid);
972         }
973         if (cpc->live_timer > 0)
974                 g_source_remove(cpc->live_timer);
975         if (cpc->client_channel)
976                 _io_channel_destroy(cpc->client_channel);
977         if (cpc->timer > 0)
978                 g_source_remove(cpc->timer);
979         if (cpc->send_fd > 0)
980                 close(cpc->send_fd);
981         __reset_slot(cpc);
982 }
983
984 static void __dispose_hydra_process(candidate_process_context_t *cpc)
985 {
986         if (!cpc)
987                 return;
988
989         __dispose_candidate_process(cpc);
990
991         _D("Dispose hydra process %d", cpc->type);
992         if (cpc->hydra_pid > 0) {
993                 _D("kill process %d", cpc->hydra_pid);
994                 __kill_process(cpc->hydra_pid);
995                 cpc->hydra_pid = HYDRA_NONE;
996         }
997
998         if (cpc->hydra_fd > 0) {
999                 close(cpc->hydra_fd);
1000                 cpc->hydra_fd = -1;
1001         }
1002 }
1003
1004 static int __send_launchpad_loader(candidate_process_context_t *cpc,
1005                 app_pkt_t *pkt, const char *app_path, int clifd)
1006 {
1007         int pid = -1;
1008         int ret;
1009
1010         ret = _delete_sock_path(cpc->pid, getuid());
1011         if (ret != 0)
1012                 return -1;
1013
1014         __candidate_process_real_launch(cpc->send_fd, pkt);
1015         SECURE_LOGD("Request to candidate process, pid: %d, bin path: %s",
1016                 cpc->pid, app_path);
1017
1018         pid = cpc->pid;
1019         cpc->pid = CANDIDATE_NONE;
1020         __dispose_candidate_process(cpc);
1021         __set_timer(cpc);
1022         __update_slot_score(cpc);
1023
1024         return pid;
1025 }
1026
1027 static int __normal_fork_exec(int argc, char **argv, const char *app_path)
1028 {
1029         char *libdir;
1030         char err_buf[1024];
1031
1032         _D("start real fork and exec");
1033
1034         libdir = _get_libdir(app_path);
1035         if (libdir) {
1036                 setenv("LD_LIBRARY_PATH", libdir, 1);
1037                 free(libdir);
1038         }
1039
1040         _close_all_fds();
1041
1042         if (execv(argv[LOADER_ARG_PATH], argv) < 0) { /* Flawfinder: ignore */
1043                 _send_message_to_logger(argv[LOADER_ARG_PATH],
1044                         "Failed to execute a file. error(%d:%s)",
1045                         errno, strerror_r(errno, err_buf, sizeof(err_buf)));
1046                 return -1;
1047         }
1048         /* never reach*/
1049         return 0;
1050 }
1051
1052 static int __create_launcher_argv(int *argc, char ***argv, const char *app_type)
1053 {
1054         int launcher_argc;
1055         char **launcher_argv;
1056         launcher_info_h launcher_info;
1057         const char *exe;
1058         const char *extra_arg;
1059         GList *extra_args;
1060         GList *iter;
1061         int i;
1062
1063         launcher_info = _launcher_info_find(launcher_info_list, app_type);
1064         if (launcher_info == NULL)
1065                 return 0;
1066
1067         exe = _launcher_info_get_exe(launcher_info);
1068         if (exe == NULL) {
1069                 _E("Failed to get launcher exe");
1070                 return -1;
1071         }
1072
1073         extra_args = _launcher_info_get_extra_args(launcher_info);
1074         launcher_argc = g_list_length(extra_args) + 1;
1075         launcher_argv = (char **)calloc(launcher_argc, sizeof(char *));
1076         if (launcher_argv == NULL) {
1077                 _E("out of memory");
1078                 return -1;
1079         }
1080
1081         i = LOADER_ARG_PATH;
1082         launcher_argv[i++] = strdup(exe);
1083
1084         iter = g_list_first(extra_args);
1085         while (iter) {
1086                 extra_arg = (const char *)iter->data;
1087                 if (extra_arg)
1088                         launcher_argv[i++] = strdup(extra_arg);
1089
1090                 iter = g_list_next(iter);
1091         }
1092
1093         *argc = launcher_argc;
1094         *argv = launcher_argv;
1095
1096
1097         return 0;
1098 }
1099
1100 static void __destroy_launcher_argv(int argc, char **argv)
1101 {
1102         int i;
1103
1104         if (argv == NULL)
1105                 return;
1106
1107         for (i = 0; i < argc; i++)
1108                 free(argv[i]);
1109         free(argv);
1110 }
1111
1112 static int __create_app_argv(int *argc, char ***argv, const char *app_path,
1113                 bundle *kb, const char *app_type)
1114 {
1115         int new_argc;
1116         char **new_argv;
1117         bool attach = false;
1118         struct app_arg debug_arg = {0,};
1119         struct app_arg launcher_arg = {0,};
1120         struct app_arg arg = {0,};
1121         struct app_arg debug_extra_arg = {0,};
1122         int ret;
1123         int i;
1124         int c;
1125
1126         ret = _debug_create_argv(&debug_arg.argc, &debug_arg.argv, &attach);
1127         if (ret < 0) {
1128                 _E("Failed to create debugger argv");
1129                 return -1;
1130         }
1131
1132         if (attach) {
1133                 *argc = debug_arg.argc;
1134                 *argv = debug_arg.argv;
1135                 return 0;
1136         }
1137
1138         ret = _debug_create_extra_argv(&debug_extra_arg.argc,
1139                         &debug_extra_arg.argv);
1140         if (ret < 0) {
1141                 _E("Failed to create debugger extra argv");
1142                 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1143                 return -1;
1144         }
1145
1146         ret = __create_launcher_argv(&launcher_arg.argc, &launcher_arg.argv,
1147                         app_type);
1148         if (ret < 0) {
1149                 _E("Failed to create launcher argv");
1150                 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
1151                 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1152                 return -1;
1153         }
1154
1155         arg.argc = bundle_export_to_argv(kb, &arg.argv);
1156         if (arg.argc <= 0) {
1157                 _E("Failed to export bundle");
1158                 __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
1159                 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
1160                 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1161                 return -1;
1162         }
1163         arg.argv[LOADER_ARG_PATH] = strdup(app_path);
1164
1165         new_argc = debug_arg.argc + launcher_arg.argc + arg.argc +
1166                 debug_extra_arg.argc;
1167         if (new_argc == arg.argc) {
1168                 *argc = arg.argc;
1169                 *argv = arg.argv;
1170                 return 0;
1171         }
1172
1173         new_argv = (char **)calloc(new_argc + 1, sizeof(char *));
1174         if (new_argv == NULL) {
1175                 _E("out of memory");
1176                 free(arg.argv[LOADER_ARG_PATH]);
1177                 bundle_free_exported_argv(arg.argc, &arg.argv);
1178                 __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
1179                 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
1180                 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1181                 return -1;
1182         }
1183
1184         c = LOADER_ARG_PATH;
1185         for (i = 0; i < debug_arg.argc; i++)
1186                 new_argv[c++] = debug_arg.argv[i];
1187         for (i = 0; i < launcher_arg.argc; i++)
1188                 new_argv[c++] = launcher_arg.argv[i];
1189         for (i = 0; i < arg.argc; i++)
1190                 new_argv[c++] = arg.argv[i];
1191         for (i = 0; i < debug_extra_arg.argc; i++)
1192                 new_argv[c++] = debug_extra_arg.argv[i];
1193
1194         *argc = new_argc;
1195         *argv = new_argv;
1196
1197         return 0;
1198 }
1199
1200 static void __real_launch(const char *app_path, bundle *kb,
1201                 appinfo_t *menu_info)
1202 {
1203         int app_argc = 0;
1204         char **app_argv;
1205         int i;
1206         int ret;
1207
1208         if (bundle_get_val(kb, AUL_K_DEBUG) != NULL)
1209                 putenv("TIZEN_DEBUGGING_PORT=1");
1210
1211         ret = __create_app_argv(&app_argc, &app_argv, app_path,
1212                         kb, menu_info->app_type);
1213         if (ret < 0) {
1214                 _E("Failed to create app argv");
1215                 exit(-1);
1216         }
1217
1218         for (i = 0; i < app_argc; i++)
1219                 SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
1220
1221         PERF("setup argument done");
1222         __normal_fork_exec(app_argc, app_argv, app_path);
1223 }
1224
1225 static int __prepare_exec(const char *appid, const char *app_path,
1226                         appinfo_t *menu_info, bundle *kb)
1227 {
1228         char *file_name;
1229         char process_name[AUL_PR_NAME];
1230         int ret;
1231
1232         /* Set new session ID & new process group ID*/
1233         /* In linux, child can set new session ID without check permission */
1234         /* TODO : should be add to check permission in the kernel*/
1235         setsid();
1236
1237         ret = _launchpad_plugin_prepare_app(appid, kb);
1238         if (ret < 0) {
1239                 _E("_launchpad_plugin_prepare_app() is failed. error(%d)", ret);
1240                 return PAD_ERR_FAILED;
1241         }
1242
1243         ret = _enable_external_pkg(kb, menu_info->pkgid,
1244                         menu_info->global ? GLOBAL_USER : getuid());
1245         if (ret < 0)
1246                 return PAD_ERR_FAILED;
1247
1248         if (menu_info->global)
1249                 ret = trust_anchor_launch(menu_info->pkgid, GLOBAL_USER);
1250         else
1251                 ret = trust_anchor_launch(menu_info->pkgid, getuid());
1252         if (ret != TRUST_ANCHOR_ERROR_NONE &&
1253                         ret != TRUST_ANCHOR_ERROR_NOT_INSTALLED) {
1254                 _E("trust_anchor_launch() returns %d", ret);
1255                 return PAD_ERR_REJECTED;
1256         }
1257
1258         /* SET PRIVILEGES*/
1259         _W("security_manager_prepare_app ++");
1260         ret = security_manager_prepare_app(appid);
1261         _W("security_manager_prepare_app --");
1262         if (ret != SECURITY_MANAGER_SUCCESS)
1263                 return PAD_ERR_REJECTED;
1264
1265         _send_cmd_to_amd(APP_STARTUP_SIGNAL);
1266         if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE)
1267                 _setup_stdio(basename(app_path));
1268
1269         /* SET DUMPABLE - for coredump*/
1270         prctl(PR_SET_DUMPABLE, 1);
1271
1272         /* SET PROCESS NAME*/
1273         if (app_path == NULL)
1274                 return PAD_ERR_INVALID_ARGUMENT;
1275
1276         file_name = strrchr(app_path, '/');
1277         if (file_name == NULL)
1278                 return PAD_ERR_INVALID_PATH;
1279
1280         file_name++;
1281         if (*file_name == '\0')
1282                 return PAD_ERR_INVALID_PATH;
1283
1284         memset(process_name, '\0', AUL_PR_NAME);
1285         snprintf(process_name, AUL_PR_NAME, "%s", file_name);
1286         prctl(PR_SET_NAME, process_name);
1287
1288         /* SET ENVIROMENT*/
1289         _set_env(menu_info, kb);
1290
1291         ret = _wait_tep_mount(kb);
1292         if (ret < 0)
1293                 return PAD_ERR_FAILED;
1294
1295         if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE) {
1296                 ret = _prepare_app_socket();
1297                 if (ret < 0)
1298                         return PAD_ERR_FAILED;
1299
1300                 ret = _prepare_id_file();
1301                 if (ret < 0)
1302                         return PAD_ERR_FAILED;
1303         }
1304
1305         return 0;
1306 }
1307
1308 static int __exec_app_process(void *arg)
1309 {
1310         struct app_launch_arg *launch_arg = arg;
1311         int ret;
1312
1313         _print_hwc_log("%d|after calling fork(). %s",
1314                         getpid(), launch_arg->appid);
1315         PERF("fork done");
1316         _D("lock up test log(no error) : fork done");
1317
1318         if (bundle_get_type(launch_arg->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
1319                 _debug_prepare_debugger(launch_arg->kb);
1320
1321         _signal_unblock_sigchld();
1322
1323         _delete_sock_path(getpid(), getuid());
1324
1325         PERF("prepare exec - first done");
1326         ret = __prepare_exec(launch_arg->appid, launch_arg->app_path,
1327                         launch_arg->menu_info, launch_arg->kb);
1328         if (ret < 0)
1329                 return ret;
1330
1331         PERF("prepare exec - second done");
1332         __real_launch(launch_arg->app_path, launch_arg->kb,
1333                         launch_arg->menu_info);
1334
1335         return PAD_ERR_FAILED;
1336 }
1337
1338 static int __launch_directly(const char *appid, const char *app_path, int clifd,
1339                 bundle *kb, appinfo_t *menu_info,
1340                 candidate_process_context_t *cpc)
1341 {
1342         struct app_launch_arg arg;
1343         int pid;
1344
1345         arg.appid = appid;
1346         arg.app_path = app_path;
1347         arg.menu_info = menu_info;
1348         arg.kb = kb;
1349
1350         _print_hwc_log("before calling fork(). %s", appid);
1351         pid = __fork_app_process(__exec_app_process, &arg);
1352         if (pid <= 0)
1353                 _E("failed to fork app process");
1354
1355         SECURE_LOGD("==> real launch pid : %d %s", pid, app_path);
1356
1357         return pid;
1358 }
1359
1360 static int __create_sock_activation(void)
1361 {
1362         int fds;
1363         char launchpad_process_pool_sock_path[108];
1364         int i;
1365
1366         fds = sd_listen_fds(0);
1367         snprintf(launchpad_process_pool_sock_path,
1368                 sizeof(launchpad_process_pool_sock_path), "%s/daemons/%u/%s",
1369                         SOCKET_PATH, getuid(), PROCESS_POOL_LAUNCHPAD_SOCK);
1370
1371         for (i = SD_LISTEN_FDS_START; i < SD_LISTEN_FDS_START + fds; ++i) {
1372                 if (sd_is_socket_unix(i, SOCK_STREAM, 1,
1373                                 launchpad_process_pool_sock_path, 0) > 0)
1374                         return i;
1375         }
1376
1377         _W("There is no socket stream");
1378         return -1;
1379 }
1380
1381 static int __launchpad_pre_init(int argc, char **argv)
1382 {
1383         int fd;
1384
1385         /* create launchpad sock */
1386         fd = __create_sock_activation();
1387         if (fd < 0) {
1388                 fd = _create_server_sock(PROCESS_POOL_LAUNCHPAD_SOCK);
1389                 if (fd < 0) {
1390                         _E("server sock error %d", fd);
1391                         return -1;
1392                 }
1393         }
1394
1395         return fd;
1396 }
1397
1398 static bool __handle_loader_client_event(int fd, io_condition_e cond,
1399                 void *data)
1400 {
1401         candidate_process_context_t *cpc = data;
1402
1403         if (cpc == NULL)
1404                 return false;
1405
1406         if (cond & (IO_HUP | IO_NVAL)) {
1407                 SECURE_LOGE("Type %d candidate process was "
1408                                 "(POLLHUP|POLLNVAL), pid: %d",
1409                                 cpc->type, cpc->pid);
1410                 cpc->pid = CANDIDATE_NONE;
1411                 __dispose_candidate_process(cpc);
1412                 __prepare_candidate_process(cpc->type, cpc->loader_id);
1413                 return false;
1414         }
1415
1416         return true;
1417
1418 }
1419
1420 static bool __handle_hydra_client_event(int fd, io_condition_e cond,
1421                 void *data)
1422 {
1423         candidate_process_context_t *cpc = data;
1424
1425         if (cpc == NULL)
1426                 return false;
1427
1428         if (cond & (IO_HUP | IO_NVAL)) {
1429                 SECURE_LOGE("Type %d hydra process was "
1430                                 "(POLLHUP|POLLNVAL), pid: %d",
1431                                 cpc->type, cpc->hydra_pid);
1432                 __dispose_hydra_process(cpc);
1433                 __prepare_candidate_process(cpc->type, cpc->loader_id);
1434                 return false;
1435         }
1436
1437         return true;
1438 }
1439
1440 static bool __handle_loader_event(int fd, io_condition_e cond, void *data)
1441 {
1442         candidate_process_context_t *cpc = data;
1443         int client_fd;
1444         int client_pid;
1445         int ret;
1446
1447         if (cpc == NULL)
1448                 return false;
1449
1450         if (!cpc->prepared) {
1451                 ret = __accept_candidate_process(fd, &client_fd, &client_pid,
1452                                         cpc->pid);
1453                 if (ret >= 0) {
1454                         /* for hydra need to set pid to pid of non-hydra candidate, */
1455                         /* which is connecting now */
1456                         if (cpc->is_hydra)
1457                                 cpc->pid = client_pid;
1458
1459                         cpc->prepared = true;
1460                         cpc->send_fd = client_fd;
1461
1462                         SECURE_LOGD("Type %d candidate process was connected, "
1463                                         "pid: %d", cpc->type, cpc->pid);
1464                         cpc->client_channel = _io_channel_create(client_fd,
1465                                         IO_IN | IO_HUP,
1466                                         __handle_loader_client_event,
1467                                         cpc);
1468                         if (!cpc->client_channel)
1469                                 close(client_fd);
1470                 }
1471         } else {
1472                 __refuse_candidate_process(fd);
1473                 _E("Refused candidate process connection");
1474         }
1475
1476         return true;
1477 }
1478
1479 static bool __handle_hydra_event(int fd, io_condition_e cond, void *data)
1480 {
1481         candidate_process_context_t *cpc = data;
1482         int client_fd;
1483         int client_pid;
1484         int ret;
1485
1486         if (cpc == NULL)
1487                 return false;
1488
1489         if (!cpc->prepared) {
1490                 ret = __accept_candidate_process(fd, &client_fd, &client_pid,
1491                                         cpc->pid);
1492                 if (ret >= 0) {
1493                         cpc->hydra_fd = client_fd;
1494
1495                         SECURE_LOGD("Type %d hydra process was connected,"
1496                                         " pid: %d", cpc->type, cpc->hydra_pid);
1497
1498                         cpc->client_channel = _io_channel_create(client_fd,
1499                                         IO_IN | IO_HUP,
1500                                         __handle_hydra_client_event,
1501                                         cpc);
1502                         if (!cpc->client_channel)
1503                                 close(client_fd);
1504                 }
1505         } else {
1506                 __refuse_candidate_process(fd);
1507                 _E("Refused hydra process connection");
1508         }
1509
1510         return true;
1511 }
1512
1513 static void __handle_sigchild(int pid, void *user_data)
1514 {
1515         candidate_process_context_t *cpc;
1516         char *appid;
1517
1518         appid = g_hash_table_lookup(__pid_table, GINT_TO_POINTER(pid));
1519         if (appid) {
1520                 security_manager_cleanup_app(appid, getuid(), pid);
1521                 g_hash_table_remove(__pid_table, GINT_TO_POINTER(pid));
1522         }
1523
1524         _log_print("[SIGCHLD]", "pid(%7d)", pid);
1525         cpc = __find_slot_from_pid(pid);
1526         if (cpc != NULL) {
1527                 cpc->pid = CANDIDATE_NONE;
1528                 __dispose_candidate_process(cpc);
1529                 __prepare_candidate_process(cpc->type, cpc->loader_id);
1530         } else {
1531                 cpc = __find_hydra_slot_from_pid(pid);
1532                 if (cpc != NULL) {
1533                         cpc->hydra_pid = HYDRA_NONE;
1534                         __dispose_hydra_process(cpc);
1535                         __prepare_candidate_process(cpc->type, cpc->loader_id);
1536                 }
1537         }
1538
1539         cpc = __find_slot_from_caller_pid(pid);
1540         while (cpc) {
1541                 __remove_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, cpc->loader_id);
1542                 cpc = __find_slot_from_caller_pid(pid);
1543         }
1544 }
1545
1546 static bool __handle_label_monitor(int fd, io_condition_e cond, void *data)
1547 {
1548         candidate_process_context_t *cpc;
1549         GList *iter = candidate_slot_list;
1550
1551         if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
1552                 _E("fd(%d), io_condition(%d)", fd, cond);
1553                 abort();
1554                 return false;
1555         }
1556
1557         _D("fd(%d) condition(%d)", fd, cond);
1558         _log_print("[LABEL]", "fd(%d), condition(%d)", fd, cond);
1559         security_manager_app_labels_monitor_process(label_monitor);
1560
1561         while (iter) {
1562                 cpc = (candidate_process_context_t *)iter->data;
1563                 if (cpc->is_hydra) {
1564                         if (cpc->hydra_pid > 0) {
1565                                 __dispose_hydra_process(cpc);
1566                                 __prepare_candidate_process(cpc->type,
1567                                                 cpc->loader_id);
1568                         }
1569                 } else if (cpc->pid > 0) {
1570                         __dispose_candidate_process(cpc);
1571                         __prepare_candidate_process(cpc->type, cpc->loader_id);
1572                 }
1573
1574                 iter = g_list_next(iter);
1575         }
1576
1577         return true;
1578 }
1579
1580 static float __interpolator(float input, int cpu_max, int cpu_min)
1581 {
1582         float ret;
1583         float min = cpu_min / 100.0f;
1584         float max = cpu_max / 100.0f;
1585
1586         if (input > 1.0f)
1587                 input = 1.0f;
1588         if (input < 0.0f)
1589                 input = 0.0f;
1590
1591         ret = cos(input * PI) / 2.0f + 0.5f;
1592         ret *= max - min;
1593         ret += min;
1594
1595         return ret;
1596 }
1597
1598 static void __update_threshold(candidate_process_context_t *cpc, float delta)
1599 {
1600         static float pos = 0.0f;
1601
1602         pos += delta;
1603         if (pos < 0.0f)
1604                 pos = 0.0f;
1605
1606         if (pos > 1.0f)
1607                 pos = 1.0f;
1608
1609         cpc->threshold = (int)(__interpolator(pos,
1610                                 cpc->threshold_max, cpc->threshold_min) * 100);
1611         _D("[CPU] type:%d / delta:%f / input cursor : %f / threshold : %d",
1612                         cpc->type, delta, pos, cpc->threshold);
1613 }
1614
1615 static gboolean __handle_idle_checker(gpointer data)
1616 {
1617         unsigned long long total = 0;
1618         unsigned long long idle = 0;
1619         int per;
1620         candidate_process_context_t *cpc;
1621
1622         if (!data) {
1623                 _E("Critical error!");
1624                 __sequencer.idle_checker = 0;
1625                 __sequencer.running_cpc = NULL;
1626                 return G_SOURCE_REMOVE;
1627         }
1628
1629         cpc = (candidate_process_context_t *)data;
1630         if (cpc->app_check && !cpc->app_exists) {
1631                 _W("The application is not installed. loader(%s:%d)",
1632                                 cpc->loader_name, cpc->type);
1633                 __sequencer.idle_checker = 0;
1634                 __sequencer.running_cpc = NULL;
1635                 return G_SOURCE_REMOVE;
1636         }
1637
1638         if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) {
1639                 _W("Slot state is not running. loader(%s:%d)",
1640                                 cpc->loader_name, cpc->type);
1641                 __sequencer.idle_checker = 0;
1642                 __sequencer.running_cpc = NULL;
1643                 return G_SOURCE_REMOVE;
1644         }
1645
1646         _get_cpu_idle(&total, &idle);
1647         if (total == cpc->cpu_total_time)
1648                 total++;
1649
1650         per = (idle - cpc->cpu_idle_time) * 100 / (total - cpc->cpu_total_time);
1651         _D("[CPU] Idle : %d / loader(%s:%d)", per, cpc->loader_name, cpc->type);
1652
1653         if (per >= cpc->threshold) {
1654                 __update_threshold(cpc, -0.02f * (per - cpc->threshold));
1655                 __prepare_candidate_process(cpc->type, cpc->loader_id);
1656                 cpc->touched = true;
1657                 __sequencer.idle_checker = 0;
1658                 __sequencer.running_cpc = NULL;
1659                 return G_SOURCE_REMOVE;
1660         }
1661
1662         cpc->cpu_idle_time = idle;
1663         cpc->cpu_total_time = total;
1664         __update_threshold(cpc, 0.05f);
1665
1666         cpc->cpu_check_count++;
1667         if (cpc->cpu_check_count == MAX_CPU_CHECK_COUNT) {
1668                 _W("CPU check count has exceeded %d times. loader(%s:%d)",
1669                                 cpc->cpu_check_count,
1670                                 cpc->loader_name,
1671                                 cpc->type);
1672                 __sequencer.idle_checker = 0;
1673                 __sequencer.running_cpc = NULL;
1674                 __sequencer_add_slot(cpc);
1675                 return G_SOURCE_REMOVE;
1676         }
1677
1678         return G_SOURCE_CONTINUE;
1679 }
1680
1681 static int __add_idle_checker(int detection_method, GList *cur)
1682 {
1683         candidate_process_context_t *cpc;
1684         GList *iter = cur;
1685
1686         while (iter) {
1687                 cpc = (candidate_process_context_t *)iter->data;
1688                 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) {
1689                         iter = g_list_next(iter);
1690                         continue;
1691                 }
1692
1693                 if (strcmp("null", cpc->loader_path) == 0) {
1694                         iter = g_list_next(iter);
1695                         continue;
1696                 }
1697
1698                 if (!cpc->touched && !cpc->on_boot) {
1699                         iter = g_list_next(iter);
1700                         continue;
1701                 }
1702
1703                 if (cpc->app_check && !cpc->app_exists) {
1704                         iter = g_list_next(iter);
1705                         continue;
1706                 }
1707
1708                 if (cpc->pid == CANDIDATE_NONE &&
1709                                 (!cpc->touched ||
1710                                  (cpc->detection_method & detection_method))) {
1711                         if (cpc->timer > 0) {
1712                                 g_source_remove(cpc->timer);
1713                                 cpc->timer = 0;
1714                         }
1715
1716                         cpc->cur_event = detection_method;
1717                         __sequencer_add_slot(cpc);
1718                         __sequencer_run();
1719                 }
1720
1721                 iter = g_list_next(iter);
1722         }
1723
1724         return -1;
1725 }
1726
1727 static int __dispatch_cmd_hint(bundle *kb, int detection_method)
1728 {
1729         _W("cmd hint %d", detection_method);
1730         __add_idle_checker(detection_method, candidate_slot_list);
1731
1732         return 0;
1733 }
1734
1735 static int __dispatch_cmd_add_loader(bundle *kb)
1736 {
1737         const char *add_slot_str = NULL;
1738         const char *caller_pid = NULL;
1739         const char *extra;
1740         int lid, size;
1741         char *loader_name;
1742         candidate_process_context_t *cpc;
1743
1744         _W("cmd add loader");
1745         add_slot_str = bundle_get_val(kb, AUL_K_LOADER_PATH);
1746         caller_pid = bundle_get_val(kb, AUL_K_CALLER_PID);
1747         extra = bundle_get_val(kb, AUL_K_LOADER_EXTRA);
1748
1749         if (add_slot_str && caller_pid) {
1750                 lid = __make_loader_id();
1751
1752                 size = snprintf(0, 0, "%s%s%d", add_slot_str, caller_pid, lid);
1753                 loader_name = (char *)malloc(size + 1);
1754                 if (loader_name == NULL) {
1755                         _E("Out of memory");
1756                         return -1;
1757                 }
1758
1759                 snprintf(loader_name, size, "%s%s%d", add_slot_str, caller_pid, lid);
1760
1761                 cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid,
1762                                 atoi(caller_pid), loader_name,
1763                                 add_slot_str, extra,
1764                                 METHOD_TIMEOUT | METHOD_VISIBILITY,
1765                                 METHOD_REQUEST | METHOD_AVAILABLE_MEMORY,
1766                                 METHOD_TTL | METHOD_OUT_OF_MEMORY,
1767                                 600,
1768                                 2000,
1769                                 DEFAULT_CPU_THRESHOLD_MAX,
1770                                 DEFAULT_CPU_THRESHOLD_MIN,
1771                                 false,
1772                                 true,
1773                                 false,
1774                                 true);
1775                 __set_timer(cpc);
1776                 free(loader_name);
1777                 return lid;
1778         }
1779
1780         return -1;
1781 }
1782
1783 static int __dispatch_cmd_add_app_defined_loader(bundle *kb)
1784 {
1785         const char *loader_name;
1786         int lid, len;
1787         candidate_process_context_t *cpc;
1788         loader_info_t *info;
1789         bundle_raw *extra;
1790
1791         _W("cmd add defined loader");
1792         loader_name = bundle_get_val(kb, AUL_K_LOADER_NAME);
1793
1794         if (loader_name == NULL) {
1795                 _E("loader_name is NULL");
1796                 return -EINVAL;
1797         }
1798
1799         info = _loader_info_find_loader_by_loader_name(
1800                         app_defined_loader_info_list, loader_name);
1801         if (info == NULL || info->extra == NULL) {
1802                 _E("loader_name %s, info  %d", loader_name, info != NULL);
1803                 return -EINVAL;
1804         }
1805
1806         bundle_encode(info->extra, &extra, &len);
1807
1808         cpc = __find_slot_from_loader_name(loader_name);
1809         if (cpc == NULL) {
1810                 lid = __make_loader_id();
1811                 cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid, 0,
1812                                 loader_name, "/usr/bin/app-defined-loader", (const char *)extra,
1813                                 METHOD_TIMEOUT | METHOD_VISIBILITY,
1814                                 METHOD_REQUEST | METHOD_AVAILABLE_MEMORY,
1815                                 METHOD_TTL | METHOD_OUT_OF_MEMORY,
1816                                 info->ttl,
1817                                 2000,
1818                                 DEFAULT_CPU_THRESHOLD_MAX,
1819                                 DEFAULT_CPU_THRESHOLD_MIN,
1820                                 false,
1821                                 true,
1822                                 false,
1823                                 true);
1824                 if (cpc == NULL) {
1825                         _E("cpc is NULL");
1826                         bundle_free_encoded_rawdata(&extra);
1827                         return -ENOMEM;
1828                 }
1829         } else {
1830                 lid = cpc->loader_id;
1831         }
1832
1833         if (cpc->pid == CANDIDATE_NONE)
1834                 __prepare_candidate_process(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid);
1835
1836         return lid;
1837 }
1838
1839 static int __dispatch_cmd_remove_loader(bundle *kb)
1840 {
1841         const char *id = bundle_get_val(kb, AUL_K_LOADER_ID);
1842         int lid;
1843
1844         _W("cmd remove loader");
1845         if (id) {
1846                 lid = atoi(id);
1847                 if (__remove_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid) == 0)
1848                         return 0;
1849         }
1850
1851         return -1;
1852 }
1853
1854 static int __check_caller_by_pid(int pid)
1855 {
1856         int ret;
1857         char buf[PATH_MAX] = { 0, };
1858
1859         ret = _proc_get_attr(pid, buf, sizeof(buf));
1860         if (ret < 0)
1861                 return -1;
1862
1863         if (strcmp(buf, "User") == 0 ||
1864                         strcmp(buf, "System") == 0 ||
1865                         strcmp(buf, "System::Privileged") == 0)
1866                 return 0;
1867
1868         return -1;
1869 }
1870
1871 static bool __is_hw_acc(const char *hwacc)
1872 {
1873         if (strcmp(hwacc, "USE") == 0 ||
1874                 (strcmp(hwacc, "SYS") == 0 &&
1875                         __sys_hwacc == SETTING_HW_ACCELERATION_ON))
1876                 return true;
1877
1878         return false;
1879 }
1880
1881 static candidate_process_context_t *__find_available_slot(const char *hwacc,
1882                 const char *app_type, const char *loader_name,
1883                 candidate_process_context_t **org_cpc)
1884 {
1885         int type;
1886         candidate_process_context_t *cpc;
1887         int *a_types;
1888         int len = 0;
1889         int i;
1890
1891         if (loader_name) {
1892                 type = _loader_info_find_type_by_loader_name(loader_info_list,
1893                                 loader_name);
1894         } else {
1895                 type = _loader_info_find_type(loader_info_list,
1896                                 app_type, __is_hw_acc(hwacc));
1897         }
1898         cpc = __find_slot(type, PAD_LOADER_ID_STATIC);
1899         if (!cpc)
1900                 return NULL;
1901
1902         *org_cpc = cpc;
1903
1904         if (cpc->prepared)
1905                 return cpc;
1906
1907         a_types = _loader_get_alternative_types(loader_info_list, type, &len);
1908         if (!a_types)
1909                 return NULL;
1910
1911         for (i = 0; i < len; i++) {
1912                 cpc = __find_slot(a_types[i], PAD_LOADER_ID_STATIC);
1913                 if (!cpc)
1914                         continue;
1915                 if (cpc->prepared) {
1916                         free(a_types);
1917                         return cpc;
1918                 }
1919         }
1920
1921         free(a_types);
1922         return NULL;
1923 }
1924
1925 static void __update_slot(int type, bool app_exists)
1926 {
1927         candidate_process_context_t *cpc;
1928
1929         cpc = __find_slot(type, PAD_LOADER_ID_STATIC);
1930         if (!cpc)
1931                 return;
1932
1933         cpc->app_exists = app_exists;
1934         if (cpc->app_check && !cpc->app_exists) {
1935                 if (cpc->pid > 0)
1936                         __dispose_candidate_process(cpc);
1937                 __sequencer_remove_slot(cpc);
1938                 if (__sequencer_queue_is_empty())
1939                         __sequencer_stop();
1940         } else {
1941                 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING)
1942                         return;
1943
1944                 if (!cpc->touched && !cpc->on_boot)
1945                         return;
1946
1947                 if (cpc->timer > 0) {
1948                         g_source_remove(cpc->timer);
1949                         cpc->timer = 0;
1950                 }
1951
1952                 if (cpc->pid == CANDIDATE_NONE) {
1953                         __sequencer_add_slot(cpc);
1954                         __sequencer_run();
1955                 }
1956         }
1957 }
1958
1959 static void __foreach_loader_info(loader_info_t *info, void *data)
1960 {
1961         struct app_info *ai = (struct app_info *)data;
1962         bool exist;
1963
1964         exist = _loader_info_exist_app_type(info, ai->type);
1965         if (!exist)
1966                 return;
1967
1968         info->app_exists = ai->exists;
1969         __update_slot(info->type, info->app_exists);
1970 }
1971
1972 static int __dispatch_cmd_update_app_type(bundle *b)
1973 {
1974         int r;
1975         struct app_info info;
1976         const char *is_installed;
1977
1978         info.type = bundle_get_val(b, AUL_K_APP_TYPE);
1979         if (!info.type)
1980                 return -1;
1981
1982         is_installed = bundle_get_val(b, AUL_K_IS_INSTALLED);
1983         if (is_installed && !strcmp(is_installed, "true"))
1984                 info.exists = true;
1985         else
1986                 info.exists = false;
1987
1988         _I("[LAUNCHPAD] type(%s), exists(%d)", info.type, info.exists);
1989
1990         r = _loader_info_foreach(loader_info_list, __foreach_loader_info,
1991                         &info);
1992         if (r != 0) {
1993                 _E("Failed to retrieve loader info");
1994                 return -1;
1995         }
1996
1997         return 0;
1998 }
1999
2000 static void __deactivate_slot(candidate_process_context_t *cpc)
2001 {
2002         if (cpc->state == CANDIDATE_PROCESS_STATE_PAUSED)
2003                 return;
2004
2005         cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
2006         __dispose_candidate_process(cpc);
2007 }
2008
2009 static void __activate_slot(candidate_process_context_t *cpc)
2010 {
2011         if (cpc->state == CANDIDATE_PROCESS_STATE_RUNNING)
2012                 return;
2013
2014         cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
2015         if (!cpc->touched && !cpc->on_boot)
2016                 return;
2017
2018         if ((cpc->app_check && !cpc->app_exists) || cpc->pid > CANDIDATE_NONE)
2019                 return;
2020
2021         if (cpc->detection_method & METHOD_TIMEOUT)
2022                 __set_timer(cpc);
2023 }
2024
2025 static void __update_slot_state(candidate_process_context_t *cpc, int method,
2026                 bool force)
2027 {
2028         switch (method) {
2029         case METHOD_OUT_OF_MEMORY:
2030                 if ((force || cpc->deactivation_method & method) &&
2031                                 __is_low_memory())
2032                         __deactivate_slot(cpc);
2033                 else
2034                         __activate_slot(cpc);
2035                 break;
2036         case METHOD_TTL:
2037                 if (force || cpc->deactivation_method & method)
2038                         __deactivate_slot(cpc);
2039                 break;
2040         case METHOD_AVAILABLE_MEMORY:
2041                 if (force || cpc->activation_method & method)
2042                         __activate_slot(cpc);
2043                 break;
2044         case METHOD_REQUEST:
2045                 if (force || cpc->activation_method & method)
2046                         __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, force);
2047                 break;
2048         default:
2049                 __activate_slot(cpc);
2050                 break;
2051         }
2052 }
2053
2054 static bool __handle_launch_event(int fd, io_condition_e cond, void *data)
2055 {
2056         bundle *kb = NULL;
2057         app_pkt_t *pkt = NULL;
2058         appinfo_t *menu_info = NULL;
2059         candidate_process_context_t *cpc = NULL;
2060         candidate_process_context_t *org_cpc = NULL;
2061         const char *app_path = NULL;
2062         int pid = -1;
2063         int clifd = -1;
2064         struct ucred cr;
2065         int type = -1;
2066         int loader_id;
2067         int ret;
2068
2069         if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
2070                 _E("fd(%d), condition(%d)", fd, cond);
2071                 g_idle_add(__launchpad_recovery_cb, __launchpad_channel);
2072                 __launchpad_channel = NULL;
2073                 return false;
2074         }
2075
2076         traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "LAUNCHPAD:LAUNCH");
2077         pkt = _accept_recv_pkt_raw(fd, &clifd, &cr);
2078         if (!pkt) {
2079                 _E("packet is NULL");
2080                 goto end;
2081         }
2082
2083         if (cr.uid >= REGULAR_UID_MIN) {
2084                 if (__check_caller_by_pid(cr.pid) < 0) {
2085                         _E("Invalid caller pid");
2086                         goto end;
2087                 }
2088         }
2089
2090         kb = bundle_decode(pkt->data, pkt->len);
2091         if (!kb) {
2092                 _E("bundle decode error");
2093                 goto end;
2094         }
2095
2096         if (bundle_get_type(kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
2097                 _debug_init();
2098
2099         switch (pkt->cmd) {
2100         case PAD_CMD_VISIBILITY:
2101                 ret = __dispatch_cmd_hint(kb, METHOD_VISIBILITY);
2102                 __real_send(clifd, ret);
2103                 clifd = -1;
2104                 goto end;
2105         case PAD_CMD_ADD_LOADER:
2106                 ret = __dispatch_cmd_add_loader(kb);
2107                 __real_send(clifd, ret);
2108                 clifd = -1;
2109                 goto end;
2110         case PAD_CMD_REMOVE_LOADER:
2111                 ret = __dispatch_cmd_remove_loader(kb);
2112                 __real_send(clifd, ret);
2113                 clifd = -1;
2114                 goto end;
2115         case PAD_CMD_MAKE_DEFAULT_SLOTS:
2116                 ret = __add_default_slots();
2117                 if (ret != 0)
2118                         _E("Failed to make default slots");
2119                 __real_send(clifd, ret);
2120                 clifd = -1;
2121                 goto end;
2122         case PAD_CMD_PREPARE_APP_DEFINED_LOADER:
2123                 ret = __dispatch_cmd_add_app_defined_loader(kb);
2124                 __real_send(clifd, ret);
2125                 clifd = -1;
2126                 goto end;
2127         case PAD_CMD_DEMAND:
2128                 ret = __dispatch_cmd_hint(kb, METHOD_DEMAND);
2129                 __real_send(clifd, ret);
2130                 clifd = -1;
2131                 goto end;
2132         case PAD_CMD_PING:
2133                 __real_send(clifd, getpid());
2134                 clifd = -1;
2135                 goto end;
2136         case PAD_CMD_UPDATE_APP_TYPE:
2137                 __dispatch_cmd_update_app_type(kb);
2138                 close(clifd);
2139                 clifd = -1;
2140                 goto end;
2141         }
2142
2143         INIT_PERF(kb);
2144         PERF("packet processing start");
2145
2146         menu_info = _appinfo_create(kb);
2147         if (menu_info == NULL) {
2148                 _E("such pkg no found");
2149                 goto end;
2150         }
2151
2152         app_path = _appinfo_get_app_path(menu_info);
2153         if (app_path == NULL) {
2154                 _E("app_path is NULL");
2155                 goto end;
2156         }
2157         if (app_path[0] != '/') {
2158                 _E("app_path is not absolute path");
2159                 goto end;
2160         }
2161
2162         if (menu_info->hwacc == NULL) {
2163                 _E("[launchpad] Failed to find H/W acceleration type");
2164                 goto end;
2165         }
2166
2167         SECURE_LOGD("exec : %s", menu_info->app_path);
2168         SECURE_LOGD("comp_type : %s", menu_info->comp_type);
2169         SECURE_LOGD("internal pool : %s", menu_info->internal_pool);
2170         SECURE_LOGD("hwacc : %s", menu_info->hwacc);
2171         SECURE_LOGD("app_type : %s", menu_info->app_type);
2172         SECURE_LOGD("pkg_type : %s", menu_info->pkg_type);
2173
2174         if (menu_info->comp_type &&
2175                         strcmp(menu_info->comp_type, "svcapp") == 0) {
2176                 loader_id = __get_loader_id(kb);
2177                 if (loader_id > PAD_LOADER_ID_DYNAMIC_BASE) {
2178                         type = LAUNCHPAD_LOADER_TYPE_DYNAMIC;
2179                         cpc = __find_slot(type, loader_id);
2180                         if (cpc && !cpc->prepared)
2181                                 cpc = NULL;
2182                 } else {
2183                         loader_id = PAD_LOADER_ID_DIRECT;
2184                 }
2185         } else if (menu_info->comp_type && menu_info->app_type &&
2186                         strcmp(menu_info->comp_type, "widgetapp") == 0 &&
2187                         strcmp(menu_info->app_type, "webapp") == 0) {
2188                 loader_id = PAD_LOADER_ID_DIRECT;
2189         } else {
2190                 loader_id = __get_loader_id(kb);
2191                 if (loader_id <= PAD_LOADER_ID_STATIC) {
2192                         cpc = __find_available_slot(menu_info->hwacc,
2193                                         menu_info->app_type,
2194                                         menu_info->loader_name, &org_cpc);
2195                 } else {
2196                         type = LAUNCHPAD_LOADER_TYPE_DYNAMIC;
2197                         cpc = __find_slot(type, loader_id);
2198                         if (cpc && !cpc->prepared)
2199                                 cpc = NULL;
2200                 }
2201         }
2202
2203         _modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
2204         if (menu_info->appid == NULL) {
2205                 _E("unable to get appid from menu_info");
2206                 goto end;
2207         }
2208
2209         PERF("get package information & modify bundle done");
2210
2211         if (loader_id == PAD_LOADER_ID_DIRECT || cpc == NULL) {
2212                 _W("Launch directly %d %p", loader_id, cpc);
2213                 pid = __launch_directly(menu_info->appid, app_path, clifd, kb,
2214                                 menu_info, NULL);
2215                 if (org_cpc && (!org_cpc->app_check || org_cpc->app_exists) &&
2216                                 org_cpc->pid == CANDIDATE_NONE &&
2217                                 !__sequencer_slot_exist(org_cpc)) {
2218                         if (org_cpc->timer > 0) {
2219                                 g_source_remove(org_cpc->timer);
2220                                 org_cpc->timer = 0;
2221                         }
2222
2223                         __update_slot_state(org_cpc, METHOD_REQUEST, true);
2224                         __set_timer(org_cpc);
2225                 }
2226         } else {
2227                 _W("Launch %d type process", cpc->type);
2228                 pid = __send_launchpad_loader(cpc, pkt, app_path, clifd);
2229         }
2230
2231         _memory_monitor_reset_timer();
2232         __send_result_to_caller(clifd, pid, app_path);
2233         clifd = -1;
2234 end:
2235         if (clifd != -1)
2236                 close(clifd);
2237
2238         if (pid > 0) {
2239                 _dbus_send_app_launch_signal(pid, menu_info->appid);
2240                 g_hash_table_insert(__pid_table, GINT_TO_POINTER(pid),
2241                                 strdup(menu_info->appid));
2242                 _log_print("[LAUNCH]", "pid(%7d) | appid(%s)",
2243                                 pid, menu_info->appid);
2244         }
2245
2246         if (menu_info != NULL)
2247                 _appinfo_free(menu_info);
2248
2249         if (kb != NULL)
2250                 bundle_free(kb);
2251         if (pkt != NULL)
2252                 free(pkt);
2253
2254         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
2255
2256         return true;
2257 }
2258
2259 static void __destroy_slot(candidate_process_context_t *cpc)
2260 {
2261         if (!cpc)
2262                 return;
2263
2264         if (cpc->hydra_channel)
2265                 _io_channel_destroy(cpc->hydra_channel);
2266
2267         if (cpc->channel)
2268                 _io_channel_destroy(cpc->channel);
2269
2270         if (cpc->loader_extra)
2271                 free(cpc->loader_extra);
2272
2273         if (cpc->loader_path)
2274                 free(cpc->loader_path);
2275
2276         if (cpc->loader_name)
2277                 free(cpc->loader_name);
2278
2279         free(cpc);
2280 }
2281
2282 static candidate_process_context_t *__create_slot(int type, int loader_id,
2283                 int caller_pid, const char *loader_name, const char *loader_path,
2284                 const char *loader_extra, int detection_method,
2285                 int activation_method, int deactivation_method,
2286                 unsigned int ttl, int timeout_val,
2287                 int threshold_max, int threshold_min,
2288                 bool on_boot, bool app_exists, bool is_hydra, bool app_check)
2289 {
2290         candidate_process_context_t *cpc;
2291
2292         cpc = calloc(1, sizeof(candidate_process_context_t));
2293         if (cpc == NULL) {
2294                 _E("Out of memory");
2295                 return NULL;
2296         }
2297
2298         cpc->loader_name = strdup(loader_name);
2299         if (cpc->loader_name == NULL) {
2300                 _E("Failed to duplicate loader name(%s)", loader_name);
2301                 __destroy_slot(cpc);
2302                 return NULL;
2303         }
2304
2305         cpc->loader_path = strdup(loader_path);
2306         if (cpc->loader_path == NULL) {
2307                 _E("Failed to duplicate loader path(%s)", loader_path);
2308                 __destroy_slot(cpc);
2309                 return NULL;
2310         }
2311
2312         cpc->loader_extra = loader_extra ? strdup(loader_extra) : strdup("");
2313         if (cpc->loader_extra == NULL) {
2314                 _E("Failed to duplicate loader extra(%s)",
2315                                 loader_extra ? loader_extra : "null");
2316                 __destroy_slot(cpc);
2317                 return NULL;
2318         }
2319
2320         cpc->type = type;
2321         cpc->prepared = false;
2322         cpc->pid = CANDIDATE_NONE;
2323         cpc->hydra_pid = HYDRA_NONE;
2324         cpc->caller_pid = caller_pid;
2325         cpc->loader_id = loader_id;
2326         cpc->send_fd = -1;
2327         cpc->hydra_fd = -1;
2328         cpc->last_exec_time = 0;
2329         cpc->timer = 0;
2330         cpc->detection_method = detection_method;
2331         cpc->timeout_val = timeout_val;
2332         cpc->cpu_total_time = 0;
2333         cpc->cpu_idle_time = 0;
2334         cpc->threshold = threshold_max;
2335         cpc->threshold_max = threshold_max;
2336         cpc->threshold_min = threshold_min;
2337         cpc->on_boot = on_boot;
2338         cpc->app_exists = app_exists;
2339         cpc->touched = false;
2340         cpc->cur_event = 0;
2341         cpc->activation_method = activation_method;
2342         cpc->deactivation_method = deactivation_method;
2343         cpc->ttl = ttl;
2344         cpc->live_timer = 0;
2345         cpc->is_hydra = is_hydra;
2346         cpc->app_check = app_check;
2347         cpc->score = WIN_SCORE;
2348         cpc->pss = 0;
2349         cpc->cpu_check_count = 0;
2350
2351         if ((cpc->deactivation_method & METHOD_OUT_OF_MEMORY) &&
2352                         __is_low_memory())
2353                 cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
2354         else
2355                 cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
2356
2357         _W("loader(%s), type(%d), state(%d)",
2358                         cpc->loader_name, cpc->type, cpc->state);
2359         return cpc;
2360 }
2361
2362 static candidate_process_context_t *__add_slot(int type, int loader_id,
2363                 int caller_pid, const char *loader_name, const char *loader_path,
2364                 const char *loader_extra, int detection_method,
2365                 int activation_method, int deactivation_method,
2366                 unsigned int ttl, int timeout_val,
2367                 int threshold_max, int threshold_min,
2368                 bool on_boot, bool app_exists, bool is_hydra, bool app_check)
2369 {
2370         candidate_process_context_t *cpc;
2371         int fd;
2372         io_channel_h channel;
2373         int hydra_fd;
2374         io_channel_h hydra_channel;
2375
2376         if (__find_slot(type, loader_id) != NULL)
2377                 return NULL;
2378
2379         cpc = __create_slot(type, loader_id,
2380                         caller_pid, loader_name, loader_path,
2381                         loader_extra, detection_method,
2382                         activation_method, deactivation_method,
2383                         ttl, timeout_val,
2384                         threshold_max, threshold_min,
2385                         on_boot, app_exists, is_hydra, app_check);
2386         if (cpc == NULL)
2387                 return NULL;
2388
2389         fd = __listen_candidate_process(cpc->type, cpc->loader_id);
2390         if (fd == -1) {
2391                 _E("[launchpad] Listening the socket to " \
2392                                 "the type %d candidate process failed.",
2393                                 cpc->type);
2394                 __destroy_slot(cpc);
2395                 return NULL;
2396         }
2397
2398         channel = _io_channel_create(fd, IO_IN, __handle_loader_event, cpc);
2399         if (!channel) {
2400                 close(fd);
2401                 __destroy_slot(cpc);
2402                 return NULL;
2403         }
2404
2405         cpc->channel = channel;
2406
2407         if (is_hydra) {
2408                 hydra_fd = __listen_hydra_process(cpc->type, cpc->loader_id);
2409                 if (hydra_fd == -1) {
2410                         _E("[launchpad] Listening the socket to " \
2411                                         "the type %d hydra process failed.",
2412                                         cpc->type);
2413                         __destroy_slot(cpc);
2414                         return NULL;
2415                 }
2416
2417                 hydra_channel = _io_channel_create(hydra_fd, IO_IN,
2418                                 __handle_hydra_event, cpc);
2419                 if (!hydra_channel) {
2420                         close(hydra_fd);
2421                         __destroy_slot(cpc);
2422                         return NULL;
2423                 }
2424
2425                 cpc->hydra_channel = hydra_channel;
2426         }
2427
2428
2429         candidate_slot_list = g_list_append(candidate_slot_list, cpc);
2430
2431         return cpc;
2432 }
2433
2434 static int __remove_slot(int type, int loader_id)
2435 {
2436         candidate_process_context_t *cpc;
2437         GList *iter;
2438
2439         iter = candidate_slot_list;
2440         while (iter) {
2441                 cpc = (candidate_process_context_t *)iter->data;
2442                 if (type == cpc->type && loader_id == cpc->loader_id) {
2443                         __dispose_candidate_process(cpc);
2444                         candidate_slot_list = g_list_delete_link(
2445                                         candidate_slot_list, iter);
2446                         __destroy_slot(cpc);
2447                         return 0;
2448                 }
2449
2450                 iter = g_list_next(iter);
2451         }
2452
2453         return -1;
2454 }
2455
2456 static int __init_launchpad_fd(int argc, char **argv)
2457 {
2458         io_condition_e cond;
2459         int fd;
2460
2461         fd = __launchpad_pre_init(argc, argv);
2462         if (fd < 0) {
2463                 _E("launchpad pre init failed");
2464                 return -1;
2465         }
2466
2467         cond = IO_IN | IO_PRI | IO_HUP | IO_ERR | IO_NVAL;
2468         __launchpad_channel = _io_channel_create(fd, cond,
2469                         __handle_launch_event, NULL);
2470         if (!__launchpad_channel) {
2471                 close(fd);
2472                 return -1;
2473         }
2474
2475         return 0;
2476 }
2477
2478 static bool __on_directory_create(const char *event_name, uint32_t mask,
2479                 void *user_data)
2480 {
2481         if (!event_name) {
2482                 _E("Invalid parameter");
2483                 return true;
2484         }
2485
2486         if (!strcmp(event_name, LOADERS_PATH)) {
2487                 __init_app_defined_loader_monitor();
2488                 return false;
2489         }
2490
2491         return true;
2492 }
2493
2494 static bool __on_file_change(const char *event_name, uint32_t mask,
2495                 void *user_data)
2496 {
2497         char buf[PATH_MAX];
2498         char *ext;
2499         loader_info_t* info;
2500         candidate_process_context_t *cpc;
2501
2502         if (!event_name) {
2503                 _E("Invalid parameter");
2504                 return true;
2505         }
2506
2507         ext = strrchr(event_name, '.');
2508         if (ext == NULL || strcmp(ext, ".loader") != 0)
2509                 return true;
2510
2511         if (mask & IN_CREATE) {
2512                 snprintf(buf, sizeof(buf), "%s/%s",
2513                                 APP_DEFINED_LOADER_INFO_PATH, event_name);
2514                 app_defined_loader_info_list = _loader_info_load_file(
2515                                 app_defined_loader_info_list, buf);
2516         } else if (mask & IN_DELETE) {
2517                 snprintf(buf, ext - event_name + 1, "%s", event_name);
2518
2519                 info = _loader_info_find_loader_by_loader_name(
2520                                 app_defined_loader_info_list, buf);
2521                 cpc = __find_slot_from_loader_name(info->name);
2522                 __remove_slot(cpc->type, cpc->loader_id);
2523                 app_defined_loader_info_list = _loader_info_unload(
2524                                 app_defined_loader_info_list, buf);
2525         }
2526
2527         return true;
2528 }
2529
2530 static void __init_app_defined_loader_monitor(void)
2531 {
2532         int ret;
2533
2534         ret = access(APP_DEFINED_LOADER_INFO_PATH, F_OK);
2535         if (ret < 0) {
2536                 _W("Failed to access %s", APP_DEFINED_LOADER_INFO_PATH);
2537                 ret = _inotify_add_watch(OPT_SHARE_PATH,
2538                                 IN_CREATE, __on_directory_create, NULL);
2539                 if (ret != 0)
2540                         _E("Failed to add inotify watch %s", OPT_SHARE_PATH);
2541
2542                 return;
2543         }
2544
2545         ret = _inotify_add_watch(APP_DEFINED_LOADER_INFO_PATH,
2546                         IN_CREATE | IN_DELETE, __on_file_change, NULL);
2547
2548         if (ret < 0) {
2549                 _E("Failed to add inotify watch %s",
2550                                 APP_DEFINED_LOADER_INFO_PATH);
2551         }
2552
2553         return;
2554
2555 }
2556
2557 static int __init_label_monitor_fd(void)
2558 {
2559         io_condition_e cond;
2560         int r;
2561         int fd = -1;
2562
2563         r = security_manager_app_labels_monitor_init(&label_monitor);
2564         if (r != SECURITY_MANAGER_SUCCESS)
2565                 return -1;
2566
2567         r = security_manager_app_labels_monitor_process(label_monitor);
2568         if (r != SECURITY_MANAGER_SUCCESS)
2569                 goto err;
2570
2571         security_manager_app_labels_monitor_get_fd(label_monitor, &fd);
2572         if (fd < 0) {
2573                 _E("failed to get fd");
2574                 goto err;
2575         }
2576
2577         cond = IO_IN | IO_PRI | IO_HUP | IO_ERR | IO_NVAL;
2578         __label_monitor_channel = _io_channel_create(fd, cond,
2579                         __handle_label_monitor, NULL);
2580         if (!__label_monitor_channel)
2581                 goto err;
2582
2583         return 0;
2584
2585 err:
2586         if (fd > 0)
2587                 close(fd);
2588
2589         if (label_monitor) {
2590                 security_manager_app_labels_monitor_finish(label_monitor);
2591                 label_monitor = NULL;
2592         }
2593
2594         return -1;
2595 }
2596
2597 static int __verify_loader_caps(const char *loader)
2598 {
2599         cap_t cap_d;
2600         cap_flag_value_t eff_state;
2601         cap_flag_value_t inh_state;
2602         cap_value_t values[] = {CAP_SETGID, CAP_MAC_ADMIN};
2603         int r;
2604         int i;
2605         int size = ARRAY_SIZE(values);
2606
2607         /* If Dytransition feature is enabled, CAP_MAC_ADMIN is unnecessary */
2608         if (label_monitor)
2609                 size--;
2610
2611         cap_d = cap_get_file(loader);
2612         if (!cap_d) {
2613                 _E("Failed to get cap from file(%s)", loader);
2614                 return -1;
2615         }
2616
2617         for (i = 0; i < size; i++) {
2618                 r = cap_get_flag(cap_d, values[i], CAP_INHERITABLE, &inh_state);
2619                 if (r != 0) {
2620                         _E("Failed to get cap inh - errno(%d)", errno);
2621                         cap_free(cap_d);
2622                         return -1;
2623                 }
2624
2625                 r = cap_get_flag(cap_d, values[i], CAP_EFFECTIVE, &eff_state);
2626                 if (r != 0) {
2627                         _E("Failed to get cap eff - errno(%d)", errno);
2628                         cap_free(cap_d);
2629                         return -1;
2630                 }
2631
2632                 if ((inh_state != CAP_SET) || (eff_state != CAP_SET)) {
2633                         _E("The %s doesn't have %d cap", loader, values[i]);
2634                         cap_free(cap_d);
2635                         return -1;
2636                 }
2637         }
2638         cap_free(cap_d);
2639
2640         return 0;
2641 }
2642
2643 static void __add_slot_from_info(gpointer data, gpointer user_data)
2644 {
2645         loader_info_t *info = (loader_info_t *)data;
2646         candidate_process_context_t *cpc;
2647         bundle_raw *extra = NULL;
2648         int len;
2649
2650         if (!strcmp(info->exe, "null")) {
2651                 cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset,
2652                                 PAD_LOADER_ID_DIRECT,
2653                                 0, info->name, info->exe, NULL,
2654                                 0, 0, 0, 0, 0,
2655                                 info->cpu_threshold_max,
2656                                 info->cpu_threshold_min,
2657                                 false,
2658                                 info->app_exists,
2659                                 info->is_hydra,
2660                                 info->app_check);
2661                 if (cpc == NULL)
2662                         return;
2663
2664                 info->type = LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset;
2665                 user_slot_offset++;
2666                 return;
2667         }
2668
2669         if (access(info->exe, F_OK | X_OK) == 0) {
2670                 if (__verify_loader_caps(info->exe) < 0)
2671                         return;
2672
2673                 if (info->extra)
2674                         bundle_encode(info->extra, &extra, &len);
2675
2676                 cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset,
2677                                 PAD_LOADER_ID_STATIC,
2678                                 0, info->name, info->exe, (char *)extra,
2679                                 info->detection_method,
2680                                 info->activation_method,
2681                                 info->deactivation_method,
2682                                 info->ttl,
2683                                 info->timeout_val,
2684                                 info->cpu_threshold_max,
2685                                 info->cpu_threshold_min,
2686                                 info->on_boot,
2687                                 info->app_exists,
2688                                 info->is_hydra,
2689                                 info->app_check);
2690                 if (cpc == NULL)
2691                         return;
2692
2693                 info->type = LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset;
2694                 user_slot_offset++;
2695         }
2696 }
2697
2698 static int __add_default_slots(void)
2699 {
2700         if (loader_info_list)
2701                 _loader_info_dispose(loader_info_list);
2702
2703         loader_info_list = _loader_info_load_dir(LOADER_INFO_PATH);
2704         if (loader_info_list == NULL)
2705                 return -1;
2706
2707         user_slot_offset = 0;
2708         g_list_foreach(loader_info_list, __add_slot_from_info, NULL);
2709         __add_idle_checker(0, candidate_slot_list);
2710
2711         return 0;
2712 }
2713
2714 static void __add_app_defined_loaders(void)
2715 {
2716         app_defined_loader_info_list = _loader_info_load_dir(APP_DEFINED_LOADER_INFO_PATH);
2717 }
2718
2719 static bool __is_low_memory(void)
2720 {
2721         if (_memory_monitor_is_low_memory())
2722                 return true;
2723
2724         if (__memory_status_low >= MEMORY_STATUS_LOW)
2725                 return true;
2726
2727         return false;
2728 }
2729
2730 static void __hw_acceleration_changed_cb(keynode_t *key, void *data)
2731 {
2732         __sys_hwacc = vconf_keynode_get_int(key);
2733         _D("sys hwacc: %d", __sys_hwacc);
2734 }
2735
2736 static void __update_lang(keynode_t *node, void *user_data)
2737 {
2738         char *lang;
2739
2740         lang = vconf_keynode_get_str(node);
2741         if (!lang) {
2742                 _E("Failed to get language");
2743                 return;
2744         }
2745
2746         setenv("LANG", lang, 1);
2747 }
2748
2749 static void __region_format_changed_cb(keynode_t *node, void *data)
2750 {
2751         char *region;
2752
2753         region = vconf_keynode_get_str(node);
2754         if (!region) {
2755                 _E("Failed to get value");
2756                 return;
2757         }
2758
2759         setenv("LC_CTYPE", region, 1);
2760 }
2761
2762 static void __memory_status_low_changed_cb(keynode_t *node, void *data)
2763 {
2764         candidate_process_context_t *cpc;
2765         GList *iter;
2766
2767         __memory_status_low = vconf_keynode_get_int(node);
2768         if (__memory_status_low >= MEMORY_STATUS_LOW) {
2769                 _W("Low memory");
2770                 iter = candidate_slot_list;
2771                 while (iter) {
2772                         cpc = (candidate_process_context_t *)iter->data;
2773                         __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, false);
2774                         iter = g_list_next(iter);
2775                 }
2776         }
2777 }
2778
2779 static void __memory_status_normal_changed_cb(keynode_t *node, void *data)
2780 {
2781         candidate_process_context_t *cpc;
2782         GList *iter;
2783
2784         __memory_status_normal = vconf_keynode_get_int(node);
2785         if (__memory_status_normal == MEMORY_STATUS_NORMAL) {
2786                 _W("Normal");
2787                 iter = candidate_slot_list;
2788                 while (iter) {
2789                         cpc = (candidate_process_context_t *)iter->data;
2790                         __update_slot_state(cpc, METHOD_AVAILABLE_MEMORY, true);
2791                         iter = g_list_next(iter);
2792                 }
2793         }
2794 }
2795
2796 static void __unregister_vconf_events(void)
2797 {
2798         const char *key;
2799         config_type_e type;
2800
2801         type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_KEY;
2802         key = _config_get_string_value(type);
2803         vconf_ignore_key_changed(key, __memory_status_normal_changed_cb);
2804
2805         type = CONFIG_TYPE_MEMORY_STATUS_LOW_KEY;
2806         key = _config_get_string_value(type);
2807         vconf_ignore_key_changed(key, __memory_status_low_changed_cb);
2808
2809         vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT,
2810                         __region_format_changed_cb);
2811         vconf_ignore_key_changed(VCONFKEY_LANGSET,
2812                         __update_lang);
2813         vconf_ignore_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION,
2814                         __hw_acceleration_changed_cb);
2815 }
2816
2817 static int __register_vconf_events(void)
2818 {
2819         int r;
2820         char *lang;
2821         char *region;
2822         const char *key;
2823         config_type_e type;
2824
2825         r = vconf_get_int(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, &__sys_hwacc);
2826         if (r != VCONF_OK)
2827                 _E("Failed to get vconf hw acceleration. err = %d", r);
2828
2829         r = vconf_notify_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION,
2830                         __hw_acceleration_changed_cb, NULL);
2831         if (r != VCONF_OK) {
2832                 _E("Failed to register callback for hw acceleration. err = %d",
2833                                 r);
2834         }
2835
2836         lang = vconf_get_str(VCONFKEY_LANGSET);
2837         if (lang) {
2838                 setenv("LANG", lang, 1);
2839                 free(lang);
2840         }
2841
2842         r = vconf_notify_key_changed(VCONFKEY_LANGSET, __update_lang, NULL);
2843         if (r != VCONF_OK)
2844                 _E("Failed to register callback for langset. err = %d", r);
2845
2846         region = vconf_get_str(VCONFKEY_REGIONFORMAT);
2847         if (region) {
2848                 setenv("LC_CTYPE", region, 1);
2849                 free(region);
2850         }
2851
2852         r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT,
2853                         __region_format_changed_cb, NULL);
2854         if (r != VCONF_OK)
2855                 _E("Failed to register callback for regionformat. err = %d", r);
2856
2857         type = CONFIG_TYPE_MEMORY_STATUS_LOW_KEY;
2858         key = _config_get_string_value(type);
2859         type = CONFIG_TYPE_MEMORY_STATUS_LOW_VALUE;
2860         MEMORY_STATUS_LOW = _config_get_int_value(type);
2861
2862         r = vconf_get_int(key, &__memory_status_low);
2863         if (r != VCONF_OK)
2864                 _E("Failed to get vconf low memory. err = %d", r);
2865
2866         r = vconf_notify_key_changed(key,
2867                         __memory_status_low_changed_cb, NULL);
2868         if (r != 0)
2869                 _E("Failed to register callback for low memory. err = %d", r);
2870
2871         type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_KEY;
2872         key = _config_get_string_value(type);
2873         type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_VALUE;
2874         MEMORY_STATUS_NORMAL = _config_get_int_value(type);
2875
2876         r = vconf_get_int(key, &__memory_status_normal);
2877         if (r != VCONF_OK)
2878                 _E("Failed to get vconf normal memory. err = %d", r);
2879
2880         r = vconf_notify_key_changed(key,
2881                         __memory_status_normal_changed_cb, NULL);
2882         if (r != 0)
2883                 _E("Failed to register callback for normal memory. err = %d", r);
2884
2885         return 0;
2886 }
2887
2888 static bool __handle_logger(int fd, io_condition_e cond, void *data)
2889 {
2890         app_pkt_t *pkt;
2891         struct ucred cr;
2892         int clifd = -1;
2893
2894         if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
2895                 _E("fd(%d), io_condition(%d)", fd, cond);
2896                 g_idle_add(__logger_recovery_cb, __logger_channel);
2897                 __logger_channel = NULL;
2898                 return false;
2899         }
2900
2901         pkt = _accept_recv_pkt_raw(fd, &clifd, &cr);
2902         if (!pkt) {
2903                 _E("Failed to receive the packet");
2904                 return true;
2905         }
2906
2907         if (getuid() != cr.uid) {
2908                 _E("Invalid caller");
2909                 goto end;
2910         }
2911
2912         if (pkt->len <= 0) {
2913                 _E("Invalid message");
2914                 goto end;
2915         }
2916
2917         _E("[%d] %s", cr.pid, (const char *)pkt->data);
2918         _log_print("[ERROR]", "pid(%7d) | message(%s)",
2919                         cr.pid, (const char *)pkt->data);
2920 end:
2921         if (clifd != -1)
2922                 close(clifd);
2923
2924         free(pkt);
2925
2926         return true;
2927 }
2928
2929 static int __init_logger_fd(void)
2930 {
2931         io_condition_e cond;
2932         int fd;
2933
2934         fd = _create_server_sock(LAUNCHPAD_LOGGER_SOCK);
2935         if (fd < 0) {
2936                 _E("Failed to create logger socker");
2937                 return -1;
2938         }
2939
2940         cond = IO_IN | IO_PRI | IO_ERR | IO_HUP | IO_NVAL;
2941         __logger_channel = _io_channel_create(fd, cond, __handle_logger, NULL);
2942         if (!__logger_channel) {
2943                 close(fd);
2944                 return -1;
2945         }
2946
2947         return 0;
2948 }
2949
2950 static int __memory_monitor_cb(bool low_memory, void *user_data)
2951 {
2952         candidate_process_context_t *cpc;
2953
2954         cpc = __get_running_slot(false);
2955         if (!cpc && low_memory)
2956                 return -1;
2957
2958         if (low_memory) {
2959                 _W("Low memory");
2960                 __update_slots_pss();
2961
2962                 candidate_slot_list = g_list_sort(candidate_slot_list,
2963                                 __compare_slot);
2964
2965                 do {
2966                         __pause_last_running_slot(false);
2967
2968                         cpc = __get_running_slot(false);
2969                         if (!cpc)
2970                                 break;
2971                 } while (__is_low_memory());
2972         } else {
2973                 __resume_all_slots();
2974         }
2975
2976         return 0;
2977 }
2978
2979 static gboolean __logger_recovery_cb(gpointer data)
2980 {
2981         io_channel_h channel = data;
2982         int ret;
2983
2984         _io_channel_destroy(channel);
2985
2986         ret = __init_logger_fd();
2987         if (ret < 0) {
2988                 _E("Failed to recover logger socket");
2989                 return G_SOURCE_REMOVE;
2990         }
2991
2992         _E("[__RECOVERY__] Logger socket");
2993
2994         return G_SOURCE_REMOVE;
2995 }
2996
2997 static gboolean __launchpad_recovery_cb(gpointer data)
2998 {
2999         io_channel_h channel = data;
3000         int ret;
3001
3002         _io_channel_destroy(channel);
3003
3004         ret = __init_launchpad_fd(0, NULL);
3005         if (ret < 0) {
3006                 _E("Failed to recover launchpad socket");
3007                 abort();
3008                 return G_SOURCE_REMOVE;
3009         }
3010
3011         _E("[__RECOVERY__] Launchpad socket");
3012
3013         return G_SOURCE_REMOVE;
3014 }
3015
3016 static int __before_loop(int argc, char **argv)
3017 {
3018         int ret;
3019
3020         ret = __sequencer_init();
3021         if (ret < 0) {
3022                 _E("Failed to initialize sequencer");
3023                 return -1;
3024         }
3025
3026         ret = _signal_init();
3027         if (ret < 0) {
3028                 _E("Failed to initialize signal");
3029                 return -1;
3030         }
3031
3032         _signal_set_sigchld_cb(__handle_sigchild, NULL);
3033
3034         ret = __init_launchpad_fd(argc, argv);
3035         if (ret != 0) {
3036                 _E("__init_launchpad_fd() failed");
3037                 return -1;
3038         }
3039
3040         ret = __init_logger_fd();
3041         if (ret != 0) {
3042                 _E("__init_logger_fd() failed");
3043                 return -1;
3044         }
3045
3046         ret = __init_label_monitor_fd();
3047         if (ret != 0)
3048                 _W("Failed to initialize label monitor");
3049
3050         ret = _config_init();
3051         if (ret != 0)
3052                 _W("Failed to initialize config");
3053
3054         ret = _dbus_init();
3055         if (ret != 0)
3056                 _W("Failed to initialize dbus");
3057
3058         _inotify_init();
3059
3060         MAX_CPU_CHECK_COUNT = _config_get_int_value(
3061                         CONFIG_TYPE_CPU_CHECKER_MAX_COUNT);
3062         __add_default_slots();
3063         launcher_info_list = _launcher_info_load(LAUNCHER_INFO_PATH);
3064
3065         __add_app_defined_loaders();
3066
3067         ret = _send_cmd_to_amd(LAUNCHPAD_LAUNCH_SIGNAL);
3068         if (ret < 0)
3069                 _W("Failed to send cmd(%d) to amd", LAUNCHPAD_LAUNCH_SIGNAL);
3070
3071         __pid_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
3072                         NULL, free);
3073         if (!__pid_table) {
3074                 _E("Failed to create pid table");
3075                 return -1;
3076         }
3077
3078         __register_vconf_events();
3079         __init_app_defined_loader_monitor();
3080         _memory_monitor_init();
3081         _memory_monitor_set_event_cb(__memory_monitor_cb, NULL);
3082         _log_init();
3083
3084         return 0;
3085 }
3086
3087 static void __after_loop(void)
3088 {
3089         _log_fini();
3090         _memory_monitor_fini();
3091         __unregister_vconf_events();
3092         if (__pid_table)
3093                 g_hash_table_destroy(__pid_table);
3094
3095         if (_send_cmd_to_amd(LAUNCHPAD_DEAD_SIGNAL) < 0)
3096                 _W("Failed to send cmd(%d) to amd", LAUNCHPAD_DEAD_SIGNAL);
3097
3098         _debug_fini();
3099         _launcher_info_unload(launcher_info_list);
3100         _dbus_fini();
3101         _config_fini();
3102         _inotify_fini();
3103         _loader_info_dispose(app_defined_loader_info_list);
3104
3105         if (__label_monitor_channel)
3106                 _io_channel_destroy(__label_monitor_channel);
3107
3108         if (label_monitor)
3109                 security_manager_app_labels_monitor_finish(label_monitor);
3110
3111         if (__logger_channel)
3112                 _io_channel_destroy(__logger_channel);
3113
3114         if (__launchpad_channel)
3115                 _io_channel_destroy(__launchpad_channel);
3116
3117         _signal_fini();
3118
3119         __sequencer_fini();
3120 }
3121
3122 int main(int argc, char **argv)
3123 {
3124         GMainLoop *mainloop = NULL;
3125
3126         mainloop = g_main_loop_new(NULL, FALSE);
3127         if (!mainloop) {
3128                 _E("Failed to create glib main loop");
3129                 return -1;
3130         }
3131
3132         if (__before_loop(argc, argv) != 0) {
3133                 _E("process-pool Initialization failed!");
3134                 return -1;
3135         }
3136
3137 #ifdef TIZEN_FEATURE_PRIORITY_CHANGE
3138         _set_priority(-12);
3139 #endif
3140         g_main_loop_run(mainloop);
3141
3142         __after_loop();
3143
3144         return -1;
3145 }
3146