From 4cc2046e84bd867b52dc32813cd82f8c69515799 Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Mon, 17 Aug 2015 14:12:01 +0900 Subject: [PATCH] Use signalfd to handle SIGCHLD Change-Id: I5b70a40908d2c6b7c68ccc7424a624b5f391b45b Signed-off-by: Sangyoon Jang --- am_session_agent/agent.c | 76 ++++++++++++++++++------------------- am_session_agent/sigchild.h | 91 +++++++++++++++++++-------------------------- 2 files changed, 74 insertions(+), 93 deletions(-) diff --git a/am_session_agent/agent.c b/am_session_agent/agent.c index 42cd475..65c9648 100644 --- a/am_session_agent/agent.c +++ b/am_session_agent/agent.c @@ -53,11 +53,15 @@ #include #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; } } } diff --git a/am_session_agent/sigchild.h b/am_session_agent/sigchild.h index b557e73..654d138 100644 --- a/am_session_agent/sigchild.h +++ b/am_session_agent/sigchild.h @@ -19,11 +19,11 @@ * */ +#include #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++) -- 2.7.4