Use signalfd to handle SIGCHLD 13/46113/3 accepted/tizen/mobile/20150817.134136 accepted/tizen/tv/20150817.134530 accepted/tizen/wearable/20150817.134811 submit/tizen/20150817.084057
authorSangyoon Jang <s89.jang@samsung.com>
Mon, 17 Aug 2015 05:12:01 +0000 (14:12 +0900)
committerSangyoon Jang <s89.jang@samsung.com>
Mon, 17 Aug 2015 05:21:55 +0000 (14:21 +0900)
Change-Id: I5b70a40908d2c6b7c68ccc7424a624b5f391b45b
Signed-off-by: Sangyoon Jang <s89.jang@samsung.com>
am_session_agent/agent.c
am_session_agent/sigchild.h

index 42cd475..65c9648 100644 (file)
 #include <rua.h>
 
 #define _static_ static inline
-#define POLLFD_MAX 1
 #define SQLITE_FLUSH_MAX       (1048576)       /* (1024*1024) */
 #define AUL_POLL_CNT           15
 #define AUL_PR_NAME                    16
 
+enum {
+       MAIN_FD = 0,
+       SIGCHLD_FD,
+       POLLFD_MAX
+};
 
 static char *agent_cmdline;
 static int initialized = 0;
@@ -81,9 +85,8 @@ _static_ int __term_app(int pid);
 _static_ int __resume_app(int pid);
 _static_ int __real_send(int clifd, int ret);
 _static_ void __send_result_to_caller(int clifd, int ret);
-_static_ void __agent_main_loop(int main_fd);
+_static_ void __agent_main_loop(struct pollfd pfds[]);
 _static_ int __agent_pre_init(int argc, char **argv);
-_static_ int __agent_post_init();
 
 
 
@@ -589,8 +592,10 @@ static void __add_history(const char *pkg_name, const char *app_path, unsigned c
                _E("rua add history error");
 }
 
-_static_ void __agent_main_loop(int main_fd)
+_static_ void __agent_main_loop(struct pollfd pfds[])
 {
+       int main_fd = pfds[MAIN_FD].fd;
+       int sigchld_fd = pfds[SIGCHLD_FD].fd;
        bundle *kb = NULL;
        app_pkt_t *pkt = NULL;
        app_info_from_db *menu_info = NULL;
@@ -659,8 +664,7 @@ _static_ void __agent_main_loop(int main_fd)
        _D("start %s: type=%s caller_uid=%d path=%s",appId,menu_info->pkg_type,uid,app_path);
 
        PERF("get package information & modify bundle done");
-       if( !strcmp(menu_info->pkg_type, "wgt") || !strcmp(menu_info->pkg_type, "rpm") || !strcmp(menu_info->pkg_type, "tpk"))
-       {
+       if (!strcmp(menu_info->pkg_type, "wgt") || !strcmp(menu_info->pkg_type, "rpm") || !strcmp(menu_info->pkg_type, "tpk")) {
                pid = fork();
                if (pid == 0) {
                        PERF("fork done");
@@ -668,7 +672,8 @@ _static_ void __agent_main_loop(int main_fd)
 
                        close(clifd);
                        close(main_fd);
-                       __signal_unset_sigchld();
+                       close(sigchld_fd);
+                       __signal_unblock_sigchld();
                        __signal_fini();
 
                        snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, getpid());
@@ -700,9 +705,7 @@ _static_ void __agent_main_loop(int main_fd)
        if (pid > 0) {
                if (is_real_launch) {
                        /*TODO: retry*/
-                       __signal_block_sigchld();
                        __send_app_launch_signal_dbus(pid);
-                       __signal_unblock_sigchld();
 
                        __add_history(appId, app_path, pkt->data);
                }
@@ -760,25 +763,6 @@ _static_ int __agent_pre_init(int argc, char **argv)
        return fd;
 }
 
-_static_ int __agent_post_init()
-{
-       /* Setting this as a global variable to keep track
-       of agent poll cnt */
-       /* static int initialized = 0;*/
-
-       if (initialized) {
-               initialized++;
-               return 0;
-       }
-
-       if (__signal_set_sigchld() < 0)
-               return -1;
-
-       initialized++;
-
-       return 0;
-}
-
 static void __send_dead_siganl_to_amd(void)
 {
        bundle *kb;
@@ -791,6 +775,7 @@ static void __send_dead_siganl_to_amd(void)
 int main(int argc, char **argv)
 {
        int main_fd;
+       int sigchld_fd;
        struct pollfd pfds[POLLFD_MAX];
        int i;
 
@@ -803,24 +788,35 @@ int main(int argc, char **argv)
                exit(-1);
        }
 
-       pfds[0].fd = main_fd;
-       pfds[0].events = POLLIN;
-       pfds[0].revents = 0;
+       pfds[MAIN_FD].fd = main_fd;
+       pfds[MAIN_FD].events = POLLIN;
+       pfds[MAIN_FD].revents = 0;
+
+       sigchld_fd = __signal_get_sigchld_fd();
+       if (sigchld_fd < 0) {
+               _E("get sigchld fd failed");
+               exit(-1);
+       }
+
+       pfds[SIGCHLD_FD].fd = sigchld_fd;
+       pfds[SIGCHLD_FD].events = POLLIN;
+       pfds[SIGCHLD_FD].revents = 0;
 
        while (loop_flag == TRUE) {
                if (poll(pfds, POLLFD_MAX, -1) < 0)
                        continue;
 
-               /* init with concerning X & EFL (because of booting
-               sequence problem)*/
-               if (__agent_post_init() < 0) {
-                       _E("agent post init failed");
-                       exit(-1);
-               }
-
                for (i = 0; i < POLLFD_MAX; i++) {
-                       if ((pfds[i].revents & POLLIN) != 0) {
-                               __agent_main_loop(pfds[i].fd);
+                       if ((pfds[i].revents & POLLIN) == 0)
+                               continue;
+
+                       switch (i) {
+                       case MAIN_FD:
+                               __agent_main_loop(pfds);
+                               break;
+                       case SIGCHLD_FD:
+                               __agent_sig_child(pfds[i].fd);
+                               break;
                        }
                }
        }
index b557e73..654d138 100644 (file)
  *
  */
 
+#include <sys/signalfd.h>
 #include "launch.h"
 #include "aul_util.h"
 #include "app_signal.h"
 
-static struct sigaction old_sigchild;
 static DBusConnection *bus = NULL;
 sigset_t oldmask;
 
@@ -166,14 +166,22 @@ static int __sigchild_action(void *data)
        return 0;
 }
 
-static void __agent_sig_child(int signo, siginfo_t *info, void *data)
+static void __agent_sig_child(int sigchld_fd)
 {
+       struct signalfd_siginfo info;
+       ssize_t s;
        int status;
        pid_t child_pid;
        pid_t child_pgid;
 
-       child_pgid = getpgid(info->si_pid);
-       _D("dead_pid = %d pgid = %d", info->si_pid, child_pgid);
+       s = read(sigchld_fd, &info, sizeof(struct signalfd_siginfo));
+       if (s != sizeof(struct signalfd_siginfo)) {
+               _E("error reading sigchld info");
+               return;
+       }
+
+       child_pgid = getpgid(info.ssi_pid);
+       _D("dead_pid = %d pgid = %d", info.ssi_pid, child_pgid);
 
        while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) {
                if (child_pid == child_pgid)
@@ -187,6 +195,17 @@ static void __agent_sig_child(int signo, siginfo_t *info, void *data)
 static inline int __signal_init(void)
 {
        int i;
+       DBusError error;
+
+       dbus_error_init(&error);
+       dbus_threads_init_default();
+       bus = dbus_bus_get_private(DBUS_BUS_SESSION, &error);
+       if (!bus) {
+               _E("Failed to connect to the D-BUS daemon: %s", error.message);
+               dbus_error_free(&error);
+               return -1;
+       }
+
        for (i = 0; i < _NSIG; i++) {
                switch (i) {
                        /* controlled by sys-assert package*/
@@ -210,66 +229,29 @@ static inline int __signal_init(void)
        return 0;
 }
 
-static inline int __signal_set_sigchld(void)
+static inline int __signal_get_sigchld_fd(void)
 {
-       struct sigaction act;
-       DBusError error;
+       sigset_t mask;
+       int sfd;
 
-       dbus_error_init(&error);
-       dbus_threads_init_default();
-       bus = dbus_bus_get_private(DBUS_BUS_SESSION, &error);
-       if (!bus) {
-               _E("Failed to connect to the D-BUS daemon: %s", error.message);
-               dbus_error_free(&error);
-               return -1;
-       }
-       /* TODO: if process stop mechanism is included,
-       should be modified (SA_NOCLDSTOP)*/
-       act.sa_handler = NULL;
-       act.sa_sigaction = __agent_sig_child;
-       sigemptyset(&act.sa_mask);
-       act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
-
-       if (sigaction(SIGCHLD, &act, &old_sigchild) < 0)
-               return -1;
-
-       return 0;
-}
-
-static inline int __signal_unset_sigchld(void)
-{
-       struct sigaction dummy;
-
-       if (bus == NULL)
-               return 0;
+       sigemptyset(&mask);
+       sigaddset(&mask, SIGCHLD);
 
-       dbus_connection_close(bus);
-       if (sigaction(SIGCHLD, &old_sigchild, &dummy) < 0)
-               return -1;
-
-       return 0;
-}
-
-static inline int __signal_block_sigchld(void)
-{
-       sigset_t newmask;
-
-       sigemptyset(&newmask);
-       sigaddset(&newmask, SIGCHLD);
+       if (sigprocmask(SIG_BLOCK, &mask, &oldmask) == -1)
+               _E("failed to sigprocmask");
 
-       if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
-               _E("SIG_BLOCK error");
+       sfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
+       if (sfd == -1) {
+               _E("failed to create signal for SIGCHLD");
                return -1;
        }
 
-       _D("SIGCHLD blocked");
-
-       return 0;
+       return sfd;
 }
 
 static inline int __signal_unblock_sigchld(void)
 {
-       if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {
+       if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {
                _E("SIG_SETMASK error");
                return -1;
        }
@@ -280,6 +262,9 @@ static inline int __signal_unblock_sigchld(void)
 
 static inline int __signal_fini(void)
 {
+       if (bus)
+               dbus_connection_close(bus);
+
 #ifndef PRELOAD_ACTIVATE
        int i;
        for (i = 0; i < _NSIG; i++)