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)
{
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]));
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());
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);
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) {
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) {
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);
static int __init_label_monitor_fd(void)
{
+ io_condition_e cond;
int r;
int fd = -1;
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;
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");
static int __init_logger_fd(void)
{
+ io_condition_e cond;
int fd;
fd = _create_server_sock(LAUNCHPAD_LOGGER_SOCK);
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;
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;
#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;
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;
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;
{
char path[LAUNCHPAD_SOCKET_PATH_SIZE];
io_channel_h channel;
+ io_condition_e cond;
socket_h socket;
int ret;
int fd;
_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);
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)
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);
static int __sigchld_fini(void)
{
- int ret;
-
if (__sigchld_channel)
_io_channel_destroy(__sigchld_channel);
_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;
}
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;
_D("SIGNAL_INIT");
__pid = getpid();
+ ret = __signal_block_sigchld();
+ if (ret < 0)
+ return ret;
+
ret = __sigchld_init();
if (ret < 0)
return ret;
_signal_set_sigchld_cb(NULL, NULL);
__hydra_sigchld_fini();
__sigchld_fini();
+ _signal_unblock_sigchld();
}