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