Handle returned events 24/237224/2
authorHwankyu Jhun <h.jhun@samsung.com>
Fri, 26 Jun 2020 05:33:53 +0000 (14:33 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Fri, 26 Jun 2020 06:28:51 +0000 (15:28 +0900)
When IO_ERR, IO_HUP or IO_NVAL is delivered, Launchpad tries to recover
the socket. If it's failed, Launchpad uses abort() to terminate itself
abnormally.

Change-Id: I0680c5a6b1899d3dac22459361a927a2591478fc
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
src/launchpad/inc/launchpad_signal.h
src/launchpad/src/launchpad.c
src/launchpad/src/launchpad_signal.c

index aea56542835d159aa0ae73ec4bc2ddf3b3f8ed43..dffd9619aac10a02e29454f799e8c5663385405f 100644 (file)
@@ -25,6 +25,8 @@ typedef void (*signal_sigchld_cb)(int pid, void *user_data);
 
 int _signal_set_sigchld_cb(signal_sigchld_cb callback, void *user_data);
 
+int _signal_unblock_sigchld(void);
+
 int _signal_init(void);
 
 void _signal_fini(void);
index 02aab1bb9a5fe93865669ec14a0908a94736aab5..97511386d4d0f83c7142e0980ea5757b961d1a75 100644 (file)
@@ -192,6 +192,8 @@ static bool __is_low_memory(void);
 static void __update_slot_state(candidate_process_context_t *cpc, int method,
                bool force);
 static void __init_app_defined_loader_monitor(void);
+static gboolean __launchpad_recovery_cb(gpointer data);
+static gboolean __logger_recovery_cb(gpointer data);
 
 static gboolean __handle_queuing_slots(gpointer data)
 {
@@ -781,7 +783,7 @@ static int __exec_loader_process(void *arg)
        char err_buf[1024];
 
        _send_cmd_to_amd(LAUNCHPAD_CHILD_PROCESS);
-       _signal_fini();
+       _signal_unblock_sigchld();
        _close_all_fds();
        _setup_stdio(basename(argv[LOADER_ARG_PATH]));
 
@@ -1296,7 +1298,7 @@ static int __exec_app_process(void *arg)
        if (bundle_get_type(launch_arg->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
                _debug_prepare_debugger(launch_arg->kb);
 
-       _signal_fini();
+       _signal_unblock_sigchld();
 
        _delete_sock_path(getpid(), getuid());
 
@@ -1517,6 +1519,12 @@ static bool __handle_label_monitor(int fd, io_condition_e cond, void *data)
        candidate_process_context_t *cpc;
        GList *iter = candidate_slot_list;
 
+       if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
+               _E("fd(%d), io_condition(%d)", fd, cond);
+               abort();
+               return false;
+       }
+
        _D("%s()", __FUNCTION__);
        security_manager_app_labels_monitor_process(label_monitor);
 
@@ -2028,6 +2036,13 @@ static bool __handle_launch_event(int fd, io_condition_e cond, void *data)
        int loader_id;
        int ret;
 
+       if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
+               _E("fd(%d), condition(%d)", fd, cond);
+               g_idle_add(__launchpad_recovery_cb, __launchpad_channel);
+               __launchpad_channel = NULL;
+               return false;
+       }
+
        traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "LAUNCHPAD:LAUNCH");
        pkt = _accept_recv_pkt_raw(fd, &clifd, &cr);
        if (!pkt) {
@@ -2408,7 +2423,8 @@ static int __remove_slot(int type, int loader_id)
 
 static int __init_launchpad_fd(int argc, char **argv)
 {
-       int fd = -1;
+       io_condition_e cond;
+       int fd;
 
        fd = __launchpad_pre_init(argc, argv);
        if (fd < 0) {
@@ -2416,7 +2432,8 @@ static int __init_launchpad_fd(int argc, char **argv)
                return -1;
        }
 
-       __launchpad_channel = _io_channel_create(fd, IO_IN,
+       cond = IO_IN | IO_PRI | IO_HUP | IO_ERR | IO_NVAL;
+       __launchpad_channel = _io_channel_create(fd, cond,
                        __handle_launch_event, NULL);
        if (!__launchpad_channel) {
                close(fd);
@@ -2507,6 +2524,7 @@ static void __init_app_defined_loader_monitor(void)
 
 static int __init_label_monitor_fd(void)
 {
+       io_condition_e cond;
        int r;
        int fd = -1;
 
@@ -2524,7 +2542,8 @@ static int __init_label_monitor_fd(void)
                goto err;
        }
 
-       __label_monitor_channel = _io_channel_create(fd, IO_IN,
+       cond = IO_IN | IO_PRI | IO_HUP | IO_ERR | IO_NVAL;
+       __label_monitor_channel = _io_channel_create(fd, cond,
                        __handle_label_monitor, NULL);
        if (!__label_monitor_channel)
                goto err;
@@ -2840,6 +2859,13 @@ static bool __handle_logger(int fd, io_condition_e cond, void *data)
        struct ucred cr;
        int clifd = -1;
 
+       if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
+               _E("fd(%d), io_condition(%d)", fd, cond);
+               g_idle_add(__logger_recovery_cb, __logger_channel);
+               __logger_channel = NULL;
+               return false;
+       }
+
        pkt = _accept_recv_pkt_raw(fd, &clifd, &cr);
        if (!pkt) {
                _E("Failed to receive the packet");
@@ -2868,6 +2894,7 @@ end:
 
 static int __init_logger_fd(void)
 {
+       io_condition_e cond;
        int fd;
 
        fd = _create_server_sock(LAUNCHPAD_LOGGER_SOCK);
@@ -2876,7 +2903,8 @@ static int __init_logger_fd(void)
                return -1;
        }
 
-       __logger_channel = _io_channel_create(fd, IO_IN, __handle_logger, NULL);
+       cond = IO_IN | IO_PRI | IO_ERR | IO_HUP | IO_NVAL;
+       __logger_channel = _io_channel_create(fd, cond, __handle_logger, NULL);
        if (!__logger_channel) {
                close(fd);
                return -1;
@@ -2914,6 +2942,43 @@ static int __memory_monitor_cb(bool low_memory, void *user_data)
        return 0;
 }
 
+static gboolean __logger_recovery_cb(gpointer data)
+{
+       io_channel_h channel = data;
+       int ret;
+
+       _io_channel_destroy(channel);
+
+       ret = __init_logger_fd();
+       if (ret < 0) {
+               _E("Failed to recover logger socket");
+               return G_SOURCE_REMOVE;
+       }
+
+       _E("[__RECOVERY__] Logger socket");
+
+       return G_SOURCE_REMOVE;
+}
+
+static gboolean __launchpad_recovery_cb(gpointer data)
+{
+       io_channel_h channel = data;
+       int ret;
+
+       _io_channel_destroy(channel);
+
+       ret = __init_launchpad_fd(0, NULL);
+       if (ret < 0) {
+               _E("Failed to recover launchpad socket");
+               abort();
+               return G_SOURCE_REMOVE;
+       }
+
+       _E("[__RECOVERY__] Launchpad socket");
+
+       return G_SOURCE_REMOVE;
+}
+
 static int __before_loop(int argc, char **argv)
 {
        int ret;
index 5ee306732b51f048909448c1b04470c167f489ff..6212ca4390c285ee0c081d9d6f0a50ec948fc6e4 100644 (file)
@@ -36,6 +36,7 @@
 #define HYDRA_SIGCHLD_SOCK          ".hydra-sigchld-sock"
 
 static pid_t __pid;
+static sigset_t __mask;
 static sigset_t __old_mask;
 static socket_h __sigchld_socket;
 static io_channel_h __sigchld_channel;
@@ -44,6 +45,9 @@ static io_channel_h __hydra_sigchld_channel;
 static signal_sigchld_cb __callback;
 static void *__user_data;
 
+static gboolean __hydra_sigchld_recovery_cb(gpointer data);
+static gboolean __sigchld_recovery_cb(gpointer data);
+
 static void __socket_garbage_collector(void)
 {
        DIR *dp;
@@ -99,6 +103,12 @@ static bool __hydra_sigchld_handler(int fd, io_condition_e cond,
        int pid = -1;
        int ret;
 
+       if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
+               _E("fd(%d), io_condition(%d)", fd, cond);
+               g_idle_add(__hydra_sigchld_recovery_cb, NULL);
+               return false;
+       }
+
        ret = _socket_accept(__hydra_sigchld_socket, &client_socket);
        if (ret < 0)
                return true;
@@ -130,6 +140,7 @@ static int __hydra_sigchld_init(void)
 {
        char path[LAUNCHPAD_SOCKET_PATH_SIZE];
        io_channel_h channel;
+       io_condition_e cond;
        socket_h socket;
        int ret;
        int fd;
@@ -142,7 +153,8 @@ static int __hydra_sigchld_init(void)
 
        _socket_get_fd(socket, &fd);
 
-       channel = _io_channel_create(fd, IO_IN | IO_PRI,
+       cond = IO_IN | IO_PRI | IO_ERR | IO_HUP | IO_NVAL;
+       channel = _io_channel_create(fd, cond,
                        __hydra_sigchld_handler, NULL);
        if (!channel) {
                _socket_destroy(socket);
@@ -180,6 +192,12 @@ static bool __sigchld_handler(int fd, io_condition_e cond, void *user_data)
        int status;
        int ret;
 
+       if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
+               _E("fd(%d), io_condition(%d)", fd, cond);
+               g_idle_add(__sigchld_recovery_cb, NULL);
+               return false;
+       }
+
        do {
                ret = _socket_read(__sigchld_socket, &info, sizeof(info));
                if (ret < 0)
@@ -203,38 +221,71 @@ static bool __sigchld_handler(int fd, io_condition_e cond, void *user_data)
        return true;
 }
 
-static int __sigchld_init(void)
+static int __signal_block_sigchld(void)
 {
-       io_channel_h channel;
-       socket_h socket;
-       sigset_t mask;
-       int sfd;
        int ret;
 
-       sigemptyset(&mask);
-       sigaddset(&mask, SIGCHLD);
+       sigemptyset(&__mask);
+       sigaddset(&__mask, SIGCHLD);
 
-       ret = sigprocmask(SIG_BLOCK, &mask, &__old_mask);
+       ret = sigprocmask(SIG_BLOCK, &__mask, &__old_mask);
        if (ret < 0) {
                ret = -errno;
                _E("sigprocmask(SIG_BLOCK) is failed. errno(%d)", errno);
                return ret;
        }
 
-       sfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
+       return 0;
+}
+
+static int __signal_get_sigchld_fd(void)
+{
+       int sfd;
+
+       sfd = signalfd(-1, &__mask, SFD_NONBLOCK | SFD_CLOEXEC);
        if (sfd < 0) {
-               ret = -errno;
+               sfd = -errno;
                _E("signalfd() is failed. errno(%d)", errno);
+               return sfd;
+       }
+
+       return sfd;
+}
+
+int _signal_unblock_sigchld(void)
+{
+       int ret;
+
+       ret = sigprocmask(SIG_SETMASK, &__old_mask, NULL);
+       if (ret < 0) {
+               ret = -errno;
+               _E("sigprocmask(SIG_SETMASK) is failed. errno(%d)", errno);
                return ret;
        }
 
+       return 0;
+}
+
+static int __sigchld_init(void)
+{
+       io_channel_h channel;
+       io_condition_e cond;
+       socket_h socket;
+       int sfd;
+       int ret;
+
+       sfd = __signal_get_sigchld_fd();
+       if (sfd < 0)
+               return sfd;
+
        ret = _socket_create_with_fd(sfd, &socket);
        if (ret < 0) {
                close(sfd);
                return ret;
        }
 
-       channel = _io_channel_create(sfd, IO_IN | IO_PRI,
+       cond = IO_IN | IO_PRI | IO_ERR | IO_HUP | IO_NVAL;
+       channel = _io_channel_create(sfd, cond,
                        __sigchld_handler, NULL);
        if (!channel) {
                _socket_destroy(socket);
@@ -250,8 +301,6 @@ static int __sigchld_init(void)
 
 static int __sigchld_fini(void)
 {
-       int ret;
-
        if (__sigchld_channel)
                _io_channel_destroy(__sigchld_channel);
 
@@ -262,13 +311,6 @@ static int __sigchld_fini(void)
                _socket_destroy(__sigchld_socket);
        }
 
-       ret = sigprocmask(SIG_SETMASK, &__old_mask, NULL);
-       if (ret < 0) {
-               ret = -errno;
-               _E("sigprocmask(SIG_SETMASK) is failed. errno(%d)", errno);
-               return ret;
-       }
-
        return 0;
 }
 
@@ -280,6 +322,40 @@ int _signal_set_sigchld_cb(signal_sigchld_cb callback, void *user_data)
        return 0;
 }
 
+static gboolean __hydra_sigchld_recovery_cb(gpointer data)
+{
+       int ret;
+
+       __hydra_sigchld_fini();
+
+       ret = __hydra_sigchld_init();
+       if (ret < 0) {
+               _E("Failed to recover hydra sigchld socket");
+               abort();
+       } else {
+               _W("[__RECOVERY__] Hydra SIGCHLD Socket");
+       }
+
+       return G_SOURCE_REMOVE;
+}
+
+static gboolean __sigchld_recovery_cb(gpointer data)
+{
+       int ret;
+
+       __sigchld_fini();
+
+       ret = __sigchld_init();
+       if (ret < 0) {
+               _E("Failed to recover sigchld fd");
+               abort();
+       } else {
+               _W("[__RECOVERY__] SIGCHLD fd");
+       }
+
+       return G_SOURCE_REMOVE;
+}
+
 int _signal_init(void)
 {
        int ret;
@@ -288,6 +364,10 @@ int _signal_init(void)
        _D("SIGNAL_INIT");
        __pid = getpid();
 
+       ret = __signal_block_sigchld();
+       if (ret < 0)
+               return ret;
+
        ret = __sigchld_init();
        if (ret < 0)
                return ret;
@@ -329,4 +409,5 @@ void _signal_fini(void)
        _signal_set_sigchld_cb(NULL, NULL);
        __hydra_sigchld_fini();
        __sigchld_fini();
+       _signal_unblock_sigchld();
 }