diff options
author | Hwankyu Jhun <h.jhun@samsung.com> | 2020-06-26 14:33:53 +0900 |
---|---|---|
committer | Hwankyu Jhun <h.jhun@samsung.com> | 2020-06-26 15:28:51 +0900 |
commit | f15e2ec921d5eb11495345db0fe2e6f2c0001d5c (patch) | |
tree | 253cc3fcf0250a9e5629ee332da0dd0c82dcdcd6 | |
parent | f6601b379e797f7e39dc40950d276722f81f6eec (diff) | |
download | launchpad-f15e2ec921d5eb11495345db0fe2e6f2c0001d5c.tar.gz launchpad-f15e2ec921d5eb11495345db0fe2e6f2c0001d5c.tar.bz2 launchpad-f15e2ec921d5eb11495345db0fe2e6f2c0001d5c.zip |
Handle returned events
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>
-rw-r--r-- | src/launchpad/inc/launchpad_signal.h | 2 | ||||
-rw-r--r-- | src/launchpad/src/launchpad.c | 77 | ||||
-rw-r--r-- | src/launchpad/src/launchpad_signal.c | 123 |
3 files changed, 175 insertions, 27 deletions
diff --git a/src/launchpad/inc/launchpad_signal.h b/src/launchpad/inc/launchpad_signal.h index aea5654..dffd961 100644 --- a/src/launchpad/inc/launchpad_signal.h +++ b/src/launchpad/inc/launchpad_signal.h @@ -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); diff --git a/src/launchpad/src/launchpad.c b/src/launchpad/src/launchpad.c index 02aab1b..9751138 100644 --- a/src/launchpad/src/launchpad.c +++ b/src/launchpad/src/launchpad.c @@ -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; diff --git a/src/launchpad/src/launchpad_signal.c b/src/launchpad/src/launchpad_signal.c index 5ee3067..6212ca4 100644 --- a/src/launchpad/src/launchpad_signal.c +++ b/src/launchpad/src/launchpad_signal.c @@ -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(); } |