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