[Prevent] Fixing issues: 10639,10649,14493,23411,25147,27764,28120
[platform/framework/web/wrt.git] / src / wrt-launchpad-daemon / launchpad_src / launchpad.c
1 /*
2  * Copyright (c) 2011 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
18 /*
19  * simple AUL daemon - launchpad 
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <dlfcn.h>
25 #include <X11/Xlib.h>
26 #include <sys/types.h>
27 #include <signal.h>
28 #include <dirent.h>
29 #include <fcntl.h>
30 #include <stdlib.h>
31 #include <sys/wait.h>
32 #include <poll.h>
33 #include <sys/prctl.h>
34 #include <malloc.h>
35
36 #include "app_sock.h"
37 #include <aul.h>
38
39 #include "config.h"
40
41 #include "menu_db_util.h"
42 #include "simple_util.h"
43 #include "access_control.h"
44 #include "preload.h"
45 #include "preexec.h"
46 #include "perf.h"
47 #include "sigchild.h"
48 #include "aul_util.h"
49
50 #include "util_x.h"
51
52 #include "gl.h"
53
54 #include <app-checker.h>
55 #include <sqlite3.h>
56
57 #define _static_ static inline
58 #define POLLFD_MAX 1
59 #define SQLITE_FLUSH_MAX        (1048576)       /* (1024*1024) */
60 #define AUL_POLL_CNT            15
61 #define AUL_PR_NAME                     16
62 #define PATH_APP_ROOT "/opt/usr/apps"
63 #define PATH_DATA "/data"
64 #define SDK_CODE_COVERAGE "CODE_COVERAGE"
65 #define SDK_DYNAMIC_ANALYSIS "DYNAMIC_ANALYSIS"
66 #define PATH_DA_SO "/home/developer/sdk_tools/da/da_probe.so"
67
68
69 static char *launchpad_cmdline;
70 static int initialized = 0;
71
72
73 _static_ void __set_oom();
74 _static_ void __set_env(app_info_from_db * menu_info, bundle * kb);
75 _static_ int __prepare_exec(const char *pkg_name,
76                             const char *app_path, app_info_from_db * menu_info,
77                             bundle * kb);
78 _static_ int __fake_launch_app(int cmd, int pid, bundle * kb);
79 _static_ char **__create_argc_argv(bundle * kb, int *margc);
80 _static_ int __normal_fork_exec(int argc, char **argv);
81 _static_ void __real_launch(const char *app_path, bundle * kb);
82 _static_ void __add_history(int caller, int callee, const char *pkgname,
83                                 bundle *b, const char *app_path);
84 static inline int __parser(const char *arg, char *out, int out_size);
85 _static_ void __modify_bundle(bundle * kb, int caller_pid,
86                             app_info_from_db * menu_info, int cmd);
87 _static_ int __child_raise_win_by_x(int pid, void *priv);
88 _static_ int __raise_win_by_x(int pid);
89 _static_ int __send_to_sigkill(int pid);
90 _static_ int __term_app(int pid);
91 _static_ int __resume_app(int pid);
92 _static_ void __real_send(int clifd, int ret);
93 _static_ void __send_result_to_caller(int clifd, int ret);
94 _static_ void __launchpad_main_loop(int main_fd);
95 _static_ int __launchpad_pre_init(int argc, char **argv);
96 _static_ int __launchpad_post_init();
97
98 extern ail_error_e ail_db_close(void);
99
100
101
102 _static_ void __set_oom()
103 {
104         char buf[MAX_LOCAL_BUFSZ];
105         FILE *fp;
106
107         /* we should reset oomadj value as default because child 
108         inherits from parent oom_adj*/
109         snprintf(buf, MAX_LOCAL_BUFSZ, "/proc/%d/oom_adj", getpid());
110         fp = fopen(buf, "w");
111         if (fp == NULL)
112                 return;
113         fprintf(fp, "%d", -16);
114         fclose(fp);
115 }
116
117 _static_ void __set_sdk_env(app_info_from_db* menu_info, char* str) {
118         char buf[MAX_LOCAL_BUFSZ];
119         int ret;
120
121         _D("key : %s / value : %s", AUL_K_SDK, str);
122         /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/
123         /* GCOV_PREFIX contains the prefix to add to the absolute paths in the object file. */
124         /*              Prefix can be absolute, or relative. The default is no prefix.  */
125         /* GCOV_PREFIX_STRIP indicates the how many initial directory names */
126         /*              to stripoff the hardwired absolute paths. Default value is 0. */
127         if (strncmp(str, SDK_CODE_COVERAGE, strlen(str)) == 0) {
128                 snprintf(buf, MAX_LOCAL_BUFSZ, PATH_APP_ROOT"/%s"PATH_DATA, _get_pkgname(menu_info));
129                 ret = setenv("GCOV_PREFIX", buf, 1);
130                 _D("GCOV_PREFIX : %d", ret);
131                 ret = setenv("GCOV_PREFIX_STRIP", "4096", 1);
132                 _D("GCOV_PREFIX_STRIP : %d", ret);
133         } else if (strncmp(str, SDK_DYNAMIC_ANALYSIS, strlen(str)) == 0) {
134                 ret = setenv("LD_PRELOAD", PATH_DA_SO, 1);
135                 _D("LD_PRELOAD : %d", ret);
136         }
137 }
138
139
140 _static_ void __set_env(app_info_from_db * menu_info, bundle * kb)
141 {
142         const char *str;
143         const char **str_array;
144         int len;
145         int i;
146
147         setenv("PKG_NAME", _get_pkgname(menu_info), 1);
148
149         USE_ENGINE("gl")
150
151         str = bundle_get_val(kb, AUL_K_STARTTIME);
152         if (str != NULL)
153                 setenv("APP_START_TIME", str, 1);
154
155         if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
156                 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
157                 if(str_array != NULL) {
158                         for (i = 0; i < len; i++) {
159                                 _D("index : [%d]", i);
160                                 __set_sdk_env(menu_info, (char *)str_array[i]);
161                         }
162                 }
163         } else {
164                 str = bundle_get_val(kb, AUL_K_SDK);
165                 if(str != NULL) {
166                         __set_sdk_env(menu_info, (char *)str);
167                 }
168         }
169         if (menu_info->hwacc != NULL)
170                 setenv("HWACC", menu_info->hwacc, 1);
171 }
172
173 _static_ int __prepare_exec(const char *pkg_name,
174                             const char *app_path, app_info_from_db * menu_info,
175                             bundle * kb)
176 {
177         char *file_name;
178         char process_name[AUL_PR_NAME];
179
180         /* Set new session ID & new process group ID*/
181         /* In linux, child can set new session ID without check permission */
182         /* TODO : should be add to check permission in the kernel*/
183         setsid();
184
185         __preexec_run(menu_info->pkg_type, pkg_name, app_path);
186
187         /* SET OOM*/
188         __set_oom();
189
190         /* SET PRIVILEGES*/
191         if (__set_access(pkg_name, menu_info->pkg_type, app_path) < 0) {
192                  _D("fail to set privileges - check your package's credential\n");
193                 return -1;
194         }
195         /* SET DUMPABLE - for coredump*/
196         prctl(PR_SET_DUMPABLE, 1);
197
198         /* SET PROCESS NAME*/
199         if (app_path == NULL) {
200                 _D("app_path should not be NULL - check menu db");
201                 return -1;
202         }
203         file_name = strrchr(app_path, '/') + 1;
204         if (file_name == NULL) {
205                 _D("can't locate file name to execute");
206                 return -1;
207         }
208         memset(process_name, '\0', AUL_PR_NAME);
209         snprintf(process_name, AUL_PR_NAME, "%s", file_name);
210         prctl(PR_SET_NAME, process_name);
211
212         /* SET ENVIROMENT*/
213         __set_env(menu_info, kb);
214
215         return 0;
216 }
217
218 _static_ int __fake_launch_app(int cmd, int pid, bundle * kb)
219 {
220         int datalen;
221         int ret;
222         bundle_raw *kb_data;
223
224         bundle_encode(kb, &kb_data, &datalen);
225         if ((ret = __app_send_raw(pid, cmd, kb_data, datalen)) < 0)
226                 _E("error request fake launch - error code = %d", ret);
227         free(kb_data);
228         return ret;
229 }
230
231 _static_ char **__create_argc_argv(bundle * kb, int *margc)
232 {
233         char **argv;
234         int argc;
235
236         argc = bundle_export_to_argv(kb, &argv);
237
238         *margc = argc;
239         return argv;
240 }
241
242 _static_ int __normal_fork_exec(int argc, char **argv)
243 {
244         _D("start real fork and exec\n");
245
246         // warning: unused parameter
247         argc = argc;
248
249         if (execv(argv[0], argv) < 0) { /* Flawfinder: ignore */
250                 if (errno == EACCES)
251                         _E("such a file is no executable - %s", argv[0]);
252                 else
253                         _E("unknown executable error - %s", argv[0]);
254                 return -1;
255         }
256         /* never reach*/
257         return 0;
258 }
259
260 _static_ void __real_launch(const char *app_path, bundle * kb)
261 {
262         int app_argc;
263         char **app_argv;
264         int i;
265
266         app_argv = __create_argc_argv(kb, &app_argc);
267
268 #ifndef NATIVE_LAUNCHPAD
269     if (__change_cmdline(app_path) < 0) {
270         _E("change cmdline fail");
271         return;
272     }
273
274     app_argv[0] = g_argv[0];
275 #else
276         app_argv[0] = strdup(app_path);
277 #endif
278
279         for (i = 0; i < app_argc; i++)
280                 _D("input argument %d : %s##", i, app_argv[i]);
281
282         PERF("setup argument done");
283         _E("lock up test log(no error) : setup argument done");
284
285         /* Temporary log: launch time checking */
286         LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path);
287
288         __preload_exec(app_argc, app_argv);
289
290         __normal_fork_exec(app_argc, app_argv);
291 }
292
293 _static_ void __add_history(int caller, int callee, const char *pkgname, 
294                                 bundle *b, const char *app_path)
295 {
296         struct history_data *hd;
297         bundle_raw *kb_data;
298         int len;
299
300         _D("***** HISTORY *****\n");
301         _D("%d ==> %d(%s) \n", caller, callee, pkgname);
302         _D("*******************\n");
303
304         if (b) {
305                 bundle_encode(b, (bundle_raw **)&kb_data, &len);
306                 hd = (struct history_data *)malloc(sizeof(char) * (len+1033));
307
308                 strncpy(hd->pkg_name, pkgname, MAX_PACKAGE_STR_SIZE-1);
309                 strncpy(hd->app_path, app_path, MAX_PACKAGE_APP_PATH_SIZE-1);
310                 hd->pid = callee;
311                 hd->len = len;
312                 memcpy(hd->data, kb_data, len);
313
314                 __app_send_raw(AUL_UTIL_PID, APP_ADD_HISTORY, (unsigned char *)hd,
315                         hd->len+1033);
316                 free(kb_data);
317                 free(hd);
318         } else {
319         hd = (struct history_data *)malloc(sizeof(struct history_data));
320
321                 strncpy(hd->pkg_name, pkgname, MAX_PACKAGE_STR_SIZE-1);
322                 strncpy(hd->app_path, app_path, MAX_PACKAGE_APP_PATH_SIZE-1);
323                 hd->pid = callee;
324                 hd->len = 0;
325
326                 __app_send_raw(AUL_UTIL_PID, APP_ADD_HISTORY, (unsigned char *)hd,
327                         1033);
328                 free(hd);
329         }
330
331         return;
332 }
333
334
335 /*
336  * Parsing original app path to retrieve default bundle
337  *
338  * -1 : Invalid sequence
339  * -2 : Buffer overflow
340  *
341  */
342 static inline int __parser(const char *arg, char *out, int out_size)
343 {
344         register int i;
345         int state = 1;
346         char *start_out = out;
347
348         if (arg == NULL || out == NULL) {
349                 /* Handles null buffer*/
350                 return 0;
351         }
352
353         for (i = 0; out_size > 1; i++) {
354                 switch (state) {
355                 case 1:
356                         switch (arg[i]) {
357                         case ' ':
358                         case '\t':
359                                 state = 5;
360                                 break;
361                         case '\0':
362                                 state = 7;
363                                 break;
364                         case '\"':
365                                 state = 2;
366                                 break;
367                         case '\\':
368                                 state = 4;
369                                 break;
370                         default:
371                                 *out = arg[i];
372                                 out++;
373                                 out_size--;
374                                 break;
375                         }
376                         break;
377                 case 2: /* escape start*/
378                         switch (arg[i]) {
379                         case '\0':
380                                 state = 6;
381                                 break;
382                         case '\"':
383                                 state = 1;
384                                 break;
385                         default:
386                                 *out = arg[i];
387                                 out++;
388                                 out_size--;
389                                 break;
390                         }
391                         break;
392                 case 4: /* character escape*/
393                         if (arg[i] == '\0') {
394                                 state = 6;
395                         } else {
396                                 *out = arg[i];
397                                 out++;
398                                 out_size--;
399                                 state = 1;
400                         }
401                         break;
402                 case 5: /* token*/
403                         if (out != start_out) {
404                                 *out = '\0';
405                                 out_size--;
406                                 return i;
407                         }
408                         i--;
409                         state = 1;
410                         break;
411                 case 6:
412                         return -1;      /* error*/
413                 case 7: /* terminate*/
414                         *out = '\0';
415                         out_size--;
416                         return 0;
417                 default:
418                         state = 6;
419                         break;  /* error*/
420                 }
421         }
422
423         if (out_size == 1) {
424                 *out = '\0';
425         }
426         /* Buffer overflow*/
427         return -2;
428 }
429
430 _static_ void __modify_bundle(bundle * kb, int caller_pid,
431                             app_info_from_db * menu_info, int cmd)
432 {
433         // warning: unused parameter
434         caller_pid = caller_pid;
435
436         bundle_del(kb, AUL_K_PKG_NAME);
437         bundle_del(kb, AUL_K_EXEC);
438         bundle_del(kb, AUL_K_PACKAGETYPE);
439         bundle_del(kb, AUL_K_HWACC);
440
441         /* Parse app_path to retrieve default bundle*/
442         if (cmd == APP_START || cmd == APP_START_RES || cmd == APP_OPEN || cmd == APP_RESUME) {
443                 char *ptr;
444                 char exe[MAX_PATH_LEN];
445                 int flag;
446
447                 ptr = _get_original_app_path(menu_info);
448
449                 flag = __parser(ptr, exe, sizeof(exe));
450                 if (flag > 0) {
451                         char key[256];
452                         char value[256];
453
454                         ptr += flag;
455                         _D("parsing app_path: EXEC - %s\n", exe);
456
457                         do {
458                                 flag = __parser(ptr, key, sizeof(key));
459                                 if (flag <= 0)
460                                         break;
461                                 ptr += flag;
462
463                                 flag = __parser(ptr, value, sizeof(value));
464                                 if (flag < 0)
465                                         break;
466                                 ptr += flag;
467
468                                 /*bundle_del(kb, key);*/
469                                 bundle_add(kb, key, value);
470                         } while (flag > 0);
471                 } else if (flag == 0) {
472                         _D("parsing app_path: No arguments\n");
473                 } else {
474                         _D("parsing app_path: Invalid argument\n");
475                 }
476         }
477 }
478
479 _static_ int __child_raise_win_by_x(int pid, void *priv)
480 {
481         // warning: unused parameter
482         priv = priv;
483
484         return x_util_raise_win(pid);
485 }
486
487 _static_ int __raise_win_by_x(int pid)
488 {
489         int pgid;
490         if (x_util_raise_win(pid) == 0)
491                 return 0;
492
493         /* support app launched by shell script*/
494         pgid = getpgid(pid);
495         _D("X raise failed. try to find first child & raise it - c:%d p:%d\n",
496            pgid, pid);
497
498         if (pgid <= 1)
499                 return -1;
500         if (__proc_iter_pgid(pgid, __child_raise_win_by_x, NULL) < 0)
501                 return -1;
502
503         return 0;
504 }
505
506 _static_ int __send_to_sigkill(int pid)
507 {
508         int pgid;
509
510         pgid = getpgid(pid);
511         if (pgid <= 1)
512                 return -1;
513
514         if (killpg(pgid, SIGKILL) < 0)
515                 return -1;
516
517         return 0;
518 }
519
520 _static_ int __term_app(int pid)
521 {
522         int dummy;
523         if (__app_send_raw
524             (pid, APP_TERM_BY_PID, (unsigned char *)&dummy, sizeof(int)) < 0) {
525                 _D("terminate packet send error - use SIGKILL");
526                 if (__send_to_sigkill(pid) < 0) {
527                         _E("fail to killing - %d\n", pid);
528                         return -1;
529                 }
530         }
531         _D("term done\n");
532         return 0;
533 }
534
535 _static_ int __resume_app(int pid)
536 {
537         int dummy;
538         int ret;
539         if ((ret =
540              __app_send_raw(pid, APP_RESUME_BY_PID, (unsigned char *)&dummy,
541                             sizeof(int))) < 0) {
542                 if (ret == -EAGAIN)
543                         _E("resume packet timeout error");
544                 else {
545                         _D("resume packet send error - use raise win");
546                         if (__raise_win_by_x(pid) < 0) {
547                                 _E("raise failed - %d resume fail\n", pid);
548                                 _E("we will term the app - %d\n", pid);
549                                 __send_to_sigkill(pid);
550                                 ret = -1;
551                         } else
552                                 ret = 0;
553                 }
554         }
555         _D("resume done\n");
556         return ret;
557 }
558
559 static int __get_caller_pid(bundle *kb)
560 {
561         const char *pid_str;
562         int pid;
563
564         pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
565         if(pid_str)
566                 goto end;
567
568         pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
569         if (pid_str == NULL)
570                 return -1;
571
572 end:
573         pid = atoi(pid_str);
574         if (pid <= 1)
575                 return -1;
576
577         return pid;
578 }
579
580 _static_ int __foward_cmd(int cmd, bundle *kb, int cr_pid)
581 {
582         int pid;
583         char tmp_pid[MAX_PID_STR_BUFSZ];
584         int datalen;
585         bundle_raw *kb_data;
586         int res;
587
588         if ((pid = __get_caller_pid(kb)) < 0)
589                         return AUL_R_ERROR;
590
591         snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", cr_pid);
592
593         bundle_add(kb, AUL_K_CALLEE_PID, tmp_pid);
594
595         bundle_encode(kb, &kb_data, &datalen);
596         if ((res = __app_send_raw(pid, cmd, kb_data, datalen)) < 0)
597                 res = AUL_R_ERROR;
598
599         free(kb_data);
600
601         return res;
602 }
603
604 _static_ void __real_send(int clifd, int ret)
605 {
606         if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
607                 if (errno == EPIPE) {
608                         _E("send failed due to EPIPE.\n");
609                 }
610                 _E("send fail to client");
611         }
612
613         close(clifd);
614 }
615
616 _static_ void __send_result_to_caller(int clifd, int ret)
617 {
618         char *cmdline;
619         int wait_count;
620         int cmdline_changed = 0;
621         int cmdline_exist = 0;
622
623         if (clifd == -1)
624                 return;
625
626         if (ret <= 1) {
627                 __real_send(clifd, ret);
628                 return;
629         }
630         /* check normally was launched?*/
631         wait_count = 1;
632         do {
633                 cmdline = __proc_get_cmdline_bypid(ret);
634                 if (cmdline == NULL) {
635                         _E("error founded when being launched with %d", ret);
636
637                 } else if (strcmp(cmdline, launchpad_cmdline)) {
638                         free(cmdline);
639                         cmdline_changed = 1;
640                         break;
641                 } else {
642                         cmdline_exist = 1;
643                         free(cmdline);
644                 }
645
646                 _D("-- now wait to change cmdline --");
647                 usleep(50 * 1000);      /* 50ms sleep*/
648                 wait_count++;
649         } while (wait_count <= 20);     /* max 50*20ms will be sleep*/
650
651         if ((!cmdline_exist) && (!cmdline_changed)) {
652                 __real_send(clifd, -1); /* abnormally launched*/
653                 return;
654         }
655
656         if (!cmdline_changed)
657                 _E("process launched, but cmdline not changed");
658
659         __real_send(clifd, ret);
660         return;
661 }
662
663 static app_info_from_db *_get_app_info_from_bundle_by_pkgname(
664                                                         const char *pkgname, bundle *kb)
665 {
666         app_info_from_db *menu_info;
667
668         menu_info = calloc(1, sizeof(app_info_from_db));
669         if (menu_info == NULL) {
670                 return NULL;
671         }
672
673         menu_info->pkg_name = strdup(pkgname);
674         menu_info->app_path = strdup(bundle_get_val(kb, AUL_K_EXEC));
675         if (menu_info->app_path != NULL)
676                 menu_info->original_app_path = strdup(menu_info->app_path);
677         menu_info->pkg_type = strdup(bundle_get_val(kb, AUL_K_PACKAGETYPE));
678         menu_info->hwacc = strdup(bundle_get_val(kb, AUL_K_HWACC));
679
680         if (!_get_app_path(menu_info)) {
681                 _free_app_info_from_db(menu_info);
682                 return NULL;
683         }
684
685         return menu_info;
686 }
687
688 _static_ void __launchpad_main_loop(int main_fd)
689 {
690         bundle *kb = NULL;
691         app_pkt_t *pkt = NULL;
692         app_info_from_db *menu_info = NULL;
693
694         const char *pkg_name = NULL;
695         const char *app_path = NULL;
696         int pid = -1;
697         int clifd = -1;
698         struct ucred cr;
699         int is_real_launch = 0;
700
701         char sock_path[UNIX_PATH_MAX] = {0,};
702
703         pkt = __app_recv_raw(main_fd, &clifd, &cr);
704         if (!pkt) {
705                 _D("packet is NULL");
706                 goto end;
707         }
708
709         kb = bundle_decode(pkt->data, pkt->len);
710         if (!kb) {
711                 _D("bundle decode error");
712                 goto end;
713         }
714
715         INIT_PERF(kb);
716         PERF("packet processing start");
717
718         pkg_name = bundle_get_val(kb, AUL_K_PKG_NAME);
719         _D("pkg name : %s\n", pkg_name);
720
721         menu_info = _get_app_info_from_bundle_by_pkgname(pkg_name, kb);
722         if (menu_info == NULL) {
723                 _D("such pkg no found");
724                 goto end;
725         }
726
727         app_path = _get_app_path(menu_info);
728         if(app_path == NULL) {
729                 _E("app_path is NULL");
730                 goto end;
731         }
732         if (app_path[0] != '/') {
733                 _D("app_path is not absolute path");
734                 goto end;
735         }
736
737         __modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
738         pkg_name = _get_pkgname(menu_info);
739
740         PERF("get package information & modify bundle done");
741
742         {
743                 pid = fork();
744                 if (pid == 0) {
745                         PERF("fork done");
746                         _E("lock up test log(no error) : fork done");
747
748                         close(clifd);
749                         close(main_fd);
750                         __signal_unset_sigchld();
751                         __signal_fini();
752
753                         snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, getpid());
754                         unlink(sock_path);
755
756                         PERF("prepare exec - first done");
757                         _E("lock up test log(no error) : prepare exec - first done");
758
759                         if (__prepare_exec(pkg_name, app_path,
760                                            menu_info, kb) < 0) {
761                                 _E("preparing work fail to launch - "
762                                    "can not launch %s\n", pkg_name);
763                                 exit(-1);
764                         }
765
766                         PERF("prepare exec - second done");
767                         _E("lock up test log(no error) : prepare exec - second done");
768
769                         __real_launch(app_path, kb);
770
771                         exit(-1);
772                 }
773                 _D("==> real launch pid : %d %s\n", pid, app_path);
774                 is_real_launch = 1;
775         }
776
777  end:
778         __send_result_to_caller(clifd, pid);
779
780         if (pid > 0) {
781                 if (is_real_launch) {
782                         /*TODO: retry*/
783                         __signal_block_sigchld();
784                         __send_app_launch_signal(pid);
785                         __signal_unblock_sigchld();
786                 }
787         }
788
789         if (menu_info != NULL)
790                 _free_app_info_from_db(menu_info);
791
792         if (kb != NULL)
793                 bundle_free(kb);
794         if (pkt != NULL)
795                 free(pkt);
796
797         /* Active Flusing for Daemon */
798         if (initialized > AUL_POLL_CNT) {
799                 sqlite3_release_memory(SQLITE_FLUSH_MAX);
800                 malloc_trim(0);
801                 initialized = 1;
802         }
803
804 }
805
806 _static_ int __launchpad_pre_init(int argc, char **argv)
807 {
808         int fd;
809
810         /* signal init*/
811         __signal_init();
812
813         /* get my(launchpad) command line*/
814         launchpad_cmdline = __proc_get_cmdline_bypid(getpid());
815         if (launchpad_cmdline == NULL) {
816                 _E("launchpad cmdline fail to get");
817                 return -1;
818         }
819         _D("launchpad cmdline = %s", launchpad_cmdline);
820
821         /* create launchpad sock        */
822         fd = __create_server_sock(WRT_LAUNCHPAD_PID);
823         if (fd < 0) {
824                 _E("server sock error");
825                 return -1;
826         }
827
828         __preload_init(argc, argv);
829
830     __preload_init_for_wrt();
831
832         __preexec_init(argc, argv);
833
834         return fd;
835 }
836
837 _static_ int __launchpad_post_init()
838 {
839         /* Setting this as a global variable to keep track 
840         of launchpad poll cnt */
841         /* static int initialized = 0;*/
842
843         if (initialized) {
844                 initialized++;
845                 return 0;
846         }
847
848         if (__signal_set_sigchld() < 0)
849                 return -1;
850
851         initialized++;
852
853         return 0;
854 }
855
856 int main(int argc, char **argv)
857 {
858         int main_fd;
859         struct pollfd pfds[POLLFD_MAX];
860         int i;
861
862         /* init without concerning X & EFL*/
863         main_fd = __launchpad_pre_init(argc, argv);
864         if (main_fd < 0) {
865                 _E("launchpad pre init failed");
866                 exit(-1);
867         }
868
869         pfds[0].fd = main_fd;
870         pfds[0].events = POLLIN;
871         pfds[0].revents = 0;
872
873         while (1) {
874                 if (poll(pfds, POLLFD_MAX, -1) < 0)
875                         continue;
876
877                 /* init with concerning X & EFL (because of booting 
878                 sequence problem)*/
879                 if (__launchpad_post_init() < 0) {
880                         _E("launcpad post init failed");
881                         exit(-1);
882                 }
883
884                 for (i = 0; i < POLLFD_MAX; i++) {
885                         if ((pfds[i].revents & POLLIN) != 0) {
886                                 __launchpad_main_loop(pfds[i].fd);
887                         }
888                 }
889         }
890 }
891