Refactor launchpad.c to use g_main_loop 11/52511/8 accepted/tizen/mobile/20151126.073405 accepted/tizen/tv/20151126.073425 accepted/tizen/wearable/20151126.073436 submit/tizen/20151126.063237
authorJunghoon, Park <jh9216.park@samsung.com>
Wed, 25 Nov 2015 02:20:13 +0000 (11:20 +0900)
committerJunghoon, Park <jh9216.park@samsung.com>
Thu, 26 Nov 2015 00:17:55 +0000 (09:17 +0900)
- use g_main_loop
- fix bug about making candicate process

Change-Id: Icc1efcbc2c1f9466baacfd1f40c226be8257efb9
Signed-off-by: Junghoon, Park <jh9216.park@samsung.com>
src/launchpad.c

index b9fcdc3..4cc02bf 100755 (executable)
@@ -16,7 +16,6 @@
 
 #define _GNU_SOURCE
 #include <stdio.h>
-#include <poll.h>
 #include <stdlib.h>
 #include <sys/prctl.h>
 #include <sys/socket.h>
@@ -29,6 +28,7 @@
 #include <time.h>
 #include <vconf.h>
 #include <systemd/sd-daemon.h>
+#include <glib.h>
 
 #include "perf.h"
 #include "launchpad_common.h"
 
 typedef struct {
        int pid;
+       int effective_pid;
        int send_fd;
        int last_exec_time;
+       guint source;
 } candidate;
 
-enum {
-       LAUNCH_PAD = 0,
-       POOL_TYPE = 1,
-       CANDIDATE_TYPE = LAUNCHPAD_TYPE_MAX + 1,
-       SIGCHLD_FD = LAUNCHPAD_TYPE_MAX * 2 + 1,
-       POLLFD_MAX = LAUNCHPAD_TYPE_MAX * 2 + 2
-};
+typedef struct {
+       GPollFD *gpollfd;
+       int type;
+} loader_context_t;
 
-static int initialized = 0;
 static candidate __candidate[LAUNCHPAD_TYPE_MAX] = {
-       { CANDIDATE_NONE, -1, 0 },
-       { CANDIDATE_NONE, -1, 0 }
+       { CANDIDATE_NONE, CANDIDATE_NONE, -1, 0, 0 },
+       { CANDIDATE_NONE, CANDIDATE_NONE, -1, 0, 0 },
+       { CANDIDATE_NONE, CANDIDATE_NONE, -1, 0, 0 }
 };
-static int launchpad_fd = -1;
-static int pool_fd[LAUNCHPAD_TYPE_MAX] = { -1, -1, -1 };
 
 static void __refuse_candidate_process(int server_fd)
 {
@@ -327,29 +324,18 @@ static void __prepare_candidate_process(int type)
                        _D("Succeeded to prepare candidate_process");
 
                exit(-1);
+       } else {
+               __candidate[type].effective_pid = pid;
        }
 }
 
-static void __sleep_safe(time_t sec)
+static gboolean __handle_preparing_candidate_process(gpointer user_data)
 {
-       struct timespec delay, remain;
-       delay.tv_sec = sec;
-       delay.tv_nsec = 0;
-       remain.tv_sec = 0;
-       remain.tv_nsec = 0;
+       int type = GPOINTER_TO_INT(user_data);
 
-       while (nanosleep(&delay, &remain)) {
-               if (errno == EINTR) {
-                       delay.tv_sec = remain.tv_sec;
-                       delay.tv_nsec = remain.tv_nsec;
-               } else {
-                       char err_str[MAX_LOCAL_BUFSZ] = { 0, };
-
-                       _D("nanosleep() failed, errno: %d (%s)", errno,
-                               strerror_r(errno, err_str, sizeof(err_str)));
-                       break;
-               }
-       }
+       __prepare_candidate_process(type);
+       _D("Prepare another candidate process");
+       return G_SOURCE_REMOVE;
 }
 
 static int __send_launchpad_loader(int type, app_pkt_t *pkt,
@@ -370,17 +356,20 @@ static int __send_launchpad_loader(int type, app_pkt_t *pkt,
        close(__candidate[type].send_fd);
 
        __candidate[type].pid = CANDIDATE_NONE;
+       __candidate[type].effective_pid = CANDIDATE_NONE;
        __candidate[type].send_fd = -1;
+       if (__candidate[type].source > 0) {
+               g_source_remove(__candidate[type].source);
+               __candidate[type].source = 0;
+       }
 
        /* Temporary log: launch time checking */
        //SECURE_LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path);
 
        __send_result_to_caller(clifd, pid, app_path); //to AMD
 
-       /* __sleep_safe(1); */ /* 1 sec */
-       __prepare_candidate_process(type);
+       g_timeout_add(1000, __handle_preparing_candidate_process, GINT_TO_POINTER(type));
 
-       _D("Prepare another candidate process");
        return pid;
 }
 
@@ -508,8 +497,222 @@ static int __launch_directly(const char *appid, const char *app_path, int clifd,
        return pid;
 }
 
-static void __launchpad_main_loop(int launchpad_fd, int *pool_fd)
+static int __create_sock_activation(void)
+{
+       int fds;
+
+       fds = sd_listen_fds(0);
+       if (fds == 1)
+               return SD_LISTEN_FDS_START;
+       else if (fds > 1)
+               _E("Too many file descriptors received.\n");
+       else
+               _D("There is no socket stream");
+
+       return -1;
+}
+
+static int __launchpad_pre_init(int argc, char **argv)
+{
+       int fd;
+
+       /* signal init*/
+       __signal_init();
+
+       /* create launchpad sock */
+       fd = __create_sock_activation();
+       if (fd < 0) {
+               fd = _create_server_sock(PROCESS_POOL_LAUNCHPAD_SOCK);
+               if (fd < 0) {
+                       _E("server sock error %d", fd);
+                       return -1;
+               }
+       }
+
+       return fd;
+}
+
+static void __preload_candidate_process()
+{
+       int i;
+
+       for (i = 0; i < LAUNCHPAD_TYPE_MAX; ++i)
+               __prepare_candidate_process(i);
+}
+
+static void __destroy_poll_data(gpointer data)
+{
+       free(data);
+}
+
+static gboolean __glib_check(GSource *src)
+{
+       GSList *fd_list;
+       GPollFD *tmp;
+
+       fd_list = src->poll_fds;
+       do {
+               tmp = (GPollFD *) fd_list->data;
+               if ((tmp->revents & (G_IO_IN | G_IO_PRI | G_IO_HUP | G_IO_NVAL)))
+                       return TRUE;
+               fd_list = fd_list->next;
+       } while (fd_list);
+
+       return FALSE;
+}
+
+static gboolean __glib_dispatch(GSource *src, GSourceFunc callback,
+               gpointer data)
+{
+       return callback(data);
+}
+
+static gboolean __glib_prepare(GSource *src, gint *timeout)
+{
+       return FALSE;
+}
+
+static GSourceFuncs funcs = {
+       .prepare = __glib_prepare,
+       .check = __glib_check,
+       .dispatch = __glib_dispatch,
+       .finalize = NULL
+};
+
+static int __poll_fd(int fd, gushort events, GSourceFunc func, int type)
+{
+       int r;
+       GPollFD *gpollfd;
+       GSource *src;
+
+       src = g_source_new(&funcs, sizeof(GSource));
+       if (!src) {
+               _E("out of memory");
+               return -1;
+       }
+
+       gpollfd = (GPollFD *) g_malloc(sizeof(GPollFD));
+       if (!gpollfd) {
+               _E("out of memory");
+               g_source_destroy(src);
+               return -1;
+       }
+
+       gpollfd->events = events;
+       gpollfd->fd = fd;
+
+       loader_context_t *lc = malloc(sizeof(loader_context_t));
+       if (lc == NULL) {
+               g_free(gpollfd);
+               g_source_destroy(src);
+               return -1;
+       }
+
+       lc->gpollfd = gpollfd;
+       lc->type = type;
+
+       g_source_add_poll(src, gpollfd);
+       g_source_set_callback(src, func,
+                       (gpointer) lc, __destroy_poll_data);
+       g_source_set_priority(src, G_PRIORITY_DEFAULT);
+
+       r = g_source_attach(src, NULL);
+       if (r  == 0) {
+               g_free(gpollfd);
+               g_source_destroy(src);
+               return -1;
+       }
+
+       return r;
+}
+
+static gboolean __handle_loader_client_event(gpointer data)
+{
+       loader_context_t *lc = (loader_context_t*) data;
+       int fd = lc->gpollfd->fd;
+       int type = lc->type;
+       gushort revents = lc->gpollfd->revents;
+
+       if (revents & (G_IO_HUP | G_IO_NVAL)) {
+               SECURE_LOGE("Type %d candidate process was (POLLHUP|POLLNVAL), pid: %d", type,
+                               __candidate[type].effective_pid);
+               close(fd);
+
+               __candidate[type].pid = CANDIDATE_NONE;
+               __candidate[type].effective_pid = CANDIDATE_NONE;
+               __candidate[type].send_fd = -1;
+               __candidate[type].source = 0;
+               __prepare_candidate_process(type);
+
+               return G_SOURCE_REMOVE;
+       }
+
+       return G_SOURCE_CONTINUE;
+}
+
+static gboolean __handle_loader_event(gpointer data)
+{
+       loader_context_t *lc = (loader_context_t*) data;
+       int fd = lc->gpollfd->fd;
+       int type = lc->type;
+       int client_fd;
+       int client_pid;
+
+       if (__candidate[type].pid == CANDIDATE_NONE) {
+               if (__accept_candidate_process(fd, &client_fd, &client_pid) >= 0) {
+                       __candidate[type].pid = client_pid;
+                       __candidate[type].send_fd = client_fd;
+
+                       SECURE_LOGD("Type %d candidate process was connected, pid: %d", type,
+                                       __candidate[type].pid);
+
+                       __candidate[type].source = __poll_fd(client_fd, G_IO_IN | G_IO_HUP,
+                                                       (GSourceFunc)__handle_loader_client_event, type);
+                       if (__candidate[type].source < 0) {
+                               close(client_fd);
+                       }
+               }
+       } else {
+               __refuse_candidate_process(fd);
+               _E("Refused candidate process connection");
+       }
+
+       return G_SOURCE_CONTINUE;
+}
+
+static gboolean __handle_sigchild(gpointer data)
+{
+       loader_context_t *lc = (loader_context_t*) data;
+       int fd = lc->gpollfd->fd;
+       struct signalfd_siginfo siginfo;
+       ssize_t s;
+       int i;
+
+       do {
+               s = read(fd, &siginfo, sizeof(struct signalfd_siginfo));
+               if (s == 0)
+                       break;
+
+               if (s != sizeof(struct signalfd_siginfo)) {
+                       _E("error reading sigchld info");
+                       break;
+               }
+               __launchpad_process_sigchld(&siginfo);
+
+               for (i = 0; i < LAUNCHPAD_TYPE_MAX; ++i) {
+                       if (__candidate[i].effective_pid == siginfo.ssi_pid) {
+                               __prepare_candidate_process(i);
+                               break;
+                       }
+               }
+       } while (s > 0);
+
+       return G_SOURCE_CONTINUE;
+}
+static gboolean __handle_launch_event(gpointer data)
 {
+       loader_context_t *lc = (loader_context_t*) data;
+       int fd = lc->gpollfd->fd;
        bundle *kb = NULL;
        app_pkt_t *pkt = NULL;
        app_info_from_db *menu_info = NULL;
@@ -522,7 +725,7 @@ static void __launchpad_main_loop(int launchpad_fd, int *pool_fd)
        struct ucred cr;
        int type = -1;
 
-       pkt = _recv_pkt_raw(launchpad_fd, &clifd, &cr);
+       pkt = _recv_pkt_raw(fd, &clifd, &cr);
        if (!pkt) {
                _E("packet is NULL");
                goto end;
@@ -615,214 +818,92 @@ end:
        if (pkt != NULL)
                free(pkt);
 
-       /* Active Flusing for Daemon */
-       if (initialized > AUL_POLL_CNT) {
-               malloc_trim(0);
-               initialized = 1;
-       }
-}
-
-static int __create_sock_activation(void)
-{
-       int fds;
-
-       fds = sd_listen_fds(0);
-       if (fds == 1)
-               return SD_LISTEN_FDS_START;
-       else if (fds > 1)
-               _E("Too many file descriptors received.\n");
-       else
-               _D("There is no socket stream");
-
-       return -1;
+       return G_SOURCE_CONTINUE;
 }
 
-static int __launchpad_pre_init(int argc, char **argv)
+static int __init_launchpad_fd(int argc, char **argv)
 {
-       int fd;
-
-       /* signal init*/
-       __signal_init();
+       int fd = -1;
 
-       /* create launchpad sock */
-       fd = __create_sock_activation();
+       fd = __launchpad_pre_init(argc, argv);
        if (fd < 0) {
-               fd = _create_server_sock(PROCESS_POOL_LAUNCHPAD_SOCK);
-               if (fd < 0) {
-                       _E("server sock error %d", fd);
-                       return -1;
-               }
+               _E("launchpad pre init failed");
+               return -1;
        }
 
-       return fd;
-}
-
-static int __launchpad_post_init()
-{
-       /* Setting this as a global variable to keep track
-       of launchpad poll cnt */
-       /* static int initialized = 0;*/
-
-       if (initialized) {
-               ++initialized;
-               return 0;
+       if (__poll_fd(fd, G_IO_IN, (GSourceFunc)__handle_launch_event, 0) < 0) {
+               close(fd);
+               return -1;
        }
 
-       ++initialized;
-
        return 0;
 }
 
-static int __init_pfds(struct pollfd *pfds, int argc, char **argv)
+static int __init_sigchild_fd(void)
 {
-       int sigchld_fd = -1;
-       int i;
-
-       /* init without concerning X & EFL*/
-       launchpad_fd = __launchpad_pre_init(argc, argv);
-       if (launchpad_fd < 0) {
-               _E("launchpad pre init failed");
-               exit(-1);
-       }
-       pfds[LAUNCH_PAD].fd  = launchpad_fd;
-       pfds[LAUNCH_PAD].events  = POLLIN;
-       pfds[LAUNCH_PAD].revents = 0;
+       int fd = -1;
 
-       for (i = 0; i < LAUNCHPAD_TYPE_MAX; ++i) {
-               pool_fd[i] = __listen_candidate_process(i);
-               if (pool_fd[i] == -1) {
-                       _E("[launchpad] Listening the socket to the type %d candidate process failed.",
-                          i);
-                       return -1;
-               }
-               pfds[POOL_TYPE + i].fd   = pool_fd[i];
-               pfds[POOL_TYPE + i].events  = POLLIN;
-               pfds[POOL_TYPE + i].revents = 0;
+       fd = __signal_get_sigchld_fd();
+       if (fd < 0) {
+               _E("failed to get sigchld fd");
+               return -1;
        }
 
-       sigchld_fd = __signal_get_sigchld_fd();
-       if (sigchld_fd == -1) {
-               _E("failed to get sigchld fd");
+       if (__poll_fd(fd, G_IO_IN, (GSourceFunc)__handle_sigchild, 0) < 0) {
+               close(fd);
                return -1;
        }
-       pfds[SIGCHLD_FD].fd = sigchld_fd;
-       pfds[SIGCHLD_FD].events = POLLIN;
-       pfds[SIGCHLD_FD].revents = 0;
 
        return 0;
 }
 
-static int __loop_begin(struct pollfd *pfds)
+static int __init_loader_fds(void)
 {
        int i;
 
-       while (1) {
-               for (i = 0; i < LAUNCHPAD_TYPE_MAX; ++i) {
-                       if (__candidate[i].pid == CANDIDATE_NONE) {
-                               pfds[CANDIDATE_TYPE + i].fd   = -1;
-                               pfds[CANDIDATE_TYPE + i].events  = 0;
-                               pfds[CANDIDATE_TYPE + i].revents = 0;
-
-                               if (DIFF(__candidate[i].last_exec_time, time(NULL)) > EXEC_CANDIDATE_EXPIRED)
-                                       __prepare_candidate_process(i);
-                       }
-               }
-
-               if (poll(pfds, POLLFD_MAX, -1) < 0)
-                       continue;
-
-               _D("pfds[LAUNCH_PAD].revent  : 0x%x", pfds[LAUNCH_PAD].revents) ;
-               for (i = 0; i < LAUNCHPAD_TYPE_MAX; ++i) {
-                       _D("pfds[POOL_TYPE + %d].revents : 0x%x", i, pfds[POOL_TYPE + i].revents) ;
-                       _D("pfds[CANDIDATE_TYPE + %d].revents : 0x%x", i,
-                          pfds[CANDIDATE_TYPE + i].revents);
-               }
+       for (i = 0; i < LAUNCHPAD_TYPE_MAX; ++i) {
+               int fd = -1;
 
-               /* init with concerning X & EFL (because of booting
-               * sequence problem)*/
-               if (__launchpad_post_init() < 0) {
-                       _E("launcpad post init failed");
+               fd = __listen_candidate_process(i);
+               if (fd == -1) {
+                       _E("[launchpad] Listening the socket to the type %d candidate process failed.",
+                          i);
                        return -1;
                }
 
-               if ((pfds[SIGCHLD_FD].revents & POLLIN) != 0) {
-                       struct signalfd_siginfo siginfo;
-                       ssize_t s;
-
-                       do {
-                               s = read(pfds[SIGCHLD_FD].fd, &siginfo, sizeof(struct signalfd_siginfo));
-                               if (s == 0)
-                                       break;
-
-                               if (s != sizeof(struct signalfd_siginfo)) {
-                                       _E("error reading sigchld info");
-                                       break;
-                               }
-                               __launchpad_process_sigchld(&siginfo);
-                       } while (s > 0);
-               }
-
-               if ((pfds[LAUNCH_PAD].revents & POLLIN) != 0) {
-                       _D("pfds[LAUNCH_PAD].revents & POLLIN");
-                       __launchpad_main_loop(pfds[LAUNCH_PAD].fd, pool_fd);
+               if (__poll_fd(fd, G_IO_IN, (GSourceFunc)__handle_loader_event, i) < 0) {
+                       close(fd);
+                       return -1;
                }
+       }
 
-               for (i = 0; i < LAUNCHPAD_TYPE_MAX; ++i) {
-                       if ((pfds[POOL_TYPE + i].revents & POLLIN) != 0) {
-                               int server_fd, client_fd;
-                               int client_pid;
-
-                               server_fd = pfds[POOL_TYPE + i].fd;
-
-                               _D("pfds[POOL_TYPE + %d].revents & POLLIN", i);
-
-                               if (__candidate[i].pid == CANDIDATE_NONE) {
-                                       if (__accept_candidate_process(server_fd, &client_fd, &client_pid) >= 0) {
-                                               __candidate[i].pid = client_pid;
-                                               __candidate[i].send_fd = client_fd;
-
-                                               pfds[CANDIDATE_TYPE + i].fd   = client_fd;
-                                               pfds[CANDIDATE_TYPE + i].events  = POLLIN | POLLHUP;
-                                               pfds[CANDIDATE_TYPE + i].revents = 0;
-
-                                               SECURE_LOGD("Type %d candidate process was connected, pid: %d", i,
-                                                       __candidate[i].pid);
-                                       }
-                               } else {
-                                       __refuse_candidate_process(server_fd);
-                                       _E("Refused candidate process connection");
-                               }
-                       }
-
-                       if ((pfds[CANDIDATE_TYPE + i].revents & (POLLHUP | POLLNVAL)) != 0) {
-                               SECURE_LOGD("pfds[CANDIDATE_TYPE + %d].revents & (POLLHUP|POLLNVAL), pid: %d",
-                                       i, __candidate[i].pid);
+       return 0;
+}
 
-                               if (pfds[CANDIDATE_TYPE + i].fd > -1)
-                                       close(pfds[CANDIDATE_TYPE + i].fd);
+static int __before_loop(int argc, char **argv)
+{
+       if (__init_sigchild_fd() != 0) {
+               _E("__init_sigchild_fd() failed");
+               return -1;
+       }
 
-                               __candidate[i].pid = CANDIDATE_NONE;
-                               __candidate[i].send_fd = -1;
+       if (__init_launchpad_fd(argc, argv) != 0) {
+               _E("__init_launchpad_fd() failed");
+               return -1;
+       }
 
-                               pfds[CANDIDATE_TYPE + i].fd   = -1;
-                               pfds[CANDIDATE_TYPE + i].events  = 0;
-                               pfds[CANDIDATE_TYPE + i].revents = 0;
-                       }
-               }
+       if (__init_loader_fds() != 0) {
+               _E("__init_loader_fds() failed");
+               return -1;
        }
 
+       __preload_candidate_process();
+
        return 0;
 }
 
-int main(int argc, char **argv)
+static void __set_priority(void)
 {
-       int i;
-       struct pollfd pfds[POLLFD_MAX];
-
-       memset(pfds, 0x00, sizeof(pfds));
-       if (__init_pfds(pfds, argc, argv) != 0)
-               goto error;
-
 #ifdef _APPFW_FEATURE_PRIORITY_CHANGE
        int res = setpriority(PRIO_PROCESS, 0, -12);
        if (res == -1) {
@@ -832,19 +913,25 @@ int main(int argc, char **argv)
                        getpid(), errno, strerror_r(errno, err_str, sizeof(err_str)));
        }
 #endif
-       if (__loop_begin(pfds) == 0)
-               return 0;
+}
 
-error:
-       if (launchpad_fd != -1)
-               close(launchpad_fd);
+int main(int argc, char **argv)
+{
+       GMainLoop *mainloop = NULL;
 
-       for (i = 0; i < LAUNCHPAD_TYPE_MAX; ++i) {
-               if (pool_fd[i] != -1)
-                       close(pool_fd[i]);
-               if (__candidate[i].send_fd != -1)
-                       close(__candidate[i].send_fd);
+       mainloop = g_main_loop_new(NULL, FALSE);
+       if (!mainloop) {
+               _E("failed to create glib main loop");
+               return -1;
+       }
+
+       if (__before_loop(argc, argv) != 0) {
+               _E("process-pool Initialization failed!\n");
+               return -1;
        }
 
+       __set_priority();
+       g_main_loop_run(mainloop);
+
        return -1;
 }