summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHwankyu Jhun <h.jhun@samsung.com>2020-06-26 14:33:53 +0900
committerHwankyu Jhun <h.jhun@samsung.com>2020-06-26 15:28:51 +0900
commitf15e2ec921d5eb11495345db0fe2e6f2c0001d5c (patch)
tree253cc3fcf0250a9e5629ee332da0dd0c82dcdcd6
parentf6601b379e797f7e39dc40950d276722f81f6eec (diff)
downloadlaunchpad-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.h2
-rw-r--r--src/launchpad/src/launchpad.c77
-rw-r--r--src/launchpad/src/launchpad_signal.c123
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();
}