From 0f396470ff1492d04c873e3597509ad6026a15ba Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Mon, 7 Mar 2016 20:56:32 +0800 Subject: [PATCH 1/2] simplify SIGCHLD handling of pod_init Signed-off-by: Lai Jiangshan --- src/init.c | 64 +++++++++--------------------------------------------- 1 file changed, 10 insertions(+), 54 deletions(-) diff --git a/src/init.c b/src/init.c index 79c3e16..e90f0fb 100644 --- a/src/init.c +++ b/src/init.c @@ -207,6 +207,11 @@ static int hyper_handle_exit(struct hyper_pod *pod) return 0; } +static void pod_init_sigchld(int sig) +{ + hyper_handle_exit(NULL); +} + static int hyper_signal_loop(struct hyper_event *de) { int size; @@ -241,47 +246,6 @@ static int hyper_signal_loop(struct hyper_event *de) return 0; } -static int pod_init_loop(struct hyper_pod *pod) -{ - int i, n; - struct epoll_event *events; - - pod->efd = epoll_create1(EPOLL_CLOEXEC); - if (pod->efd < 0) { - perror("epoll_create failed"); - return -1; - } - - fprintf(stdout, "hyper_init_event pod signal event %p, ops %p, fd %d\n", - &pod->sig, &hyper_signal_ops, pod->sig.fd); - if (hyper_init_event(&pod->sig, &hyper_signal_ops, NULL) < 0 || - hyper_add_event(pod->efd, &pod->sig, EPOLLIN) < 0) { - return -1; - } - - events = calloc(MAXEVENTS, sizeof(*events)); - - while (1) { - n = epoll_wait(pod->efd, events, MAXEVENTS, -1); - fprintf(stdout, "%s epoll_wait %d\n", __func__, n); - - if (n < 0) { - if (errno == EINTR) - continue; - perror("pod wait event failed"); - return -1; - } - - for (i = 0; i < n; i++) { - if (hyper_handle_event(pod->efd, &events[i]) < 0) - return -1; - } - } - - close(pod->efd); - return 0; -} - struct hyper_pod_arg { struct hyper_pod *pod; int ctl_pipe[2]; @@ -299,21 +263,13 @@ static int hyper_pod_init(void *data) close(ctl.chan.fd); close(ctl.tty.fd); - pod->sig.fd = -1; - sigemptyset(&mask); sigaddset(&mask, SIGCHLD); - - if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) { + if (sigprocmask(SIG_UNBLOCK, &mask, NULL) < 0) { perror("sigprocmask SIGCHLD failed"); - goto fail; - } - - pod->sig.fd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC); - if (pod->sig.fd < 0) { - perror("create pod signalfd failed"); - goto fail; + return -1; } + signal(SIGCHLD, pod_init_sigchld); /* mount new proc directory */ if (umount("/proc") < 0) { @@ -338,8 +294,8 @@ static int hyper_pod_init(void *data) close(arg->ctl_pipe[1]); - pod_init_loop(pod); - fprintf(stdout, "pod init exit\n"); + for (;;) + ; /* infinite loop and handle SIGCHLD */ out: _exit(-1); From 220677d76d5d01bd4e66d6c2e71143c3768b8c5c Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Mon, 7 Mar 2016 21:41:58 +0800 Subject: [PATCH 2/2] simplify SIGCHLD handling of hyper_init It uses epoll_pwait() instead of epoll_wait(), and ensures that the SIGCHLD handling and the events handling are exclusive. Signed-off-by: Lai Jiangshan --- src/hyper.h | 2 -- src/init.c | 84 ++++++++++++----------------------------------------- 2 files changed, 19 insertions(+), 67 deletions(-) diff --git a/src/hyper.h b/src/hyper.h index d930e7e..a442eff 100644 --- a/src/hyper.h +++ b/src/hyper.h @@ -57,7 +57,6 @@ struct hyper_pod { uint32_t remains; uint8_t policy; int efd; - struct hyper_event sig; }; struct hyper_win_size { @@ -86,7 +85,6 @@ struct hyper_writter { struct hyper_ctl { int efd; - struct hyper_event sig; struct hyper_event tty; struct hyper_event chan; }; diff --git a/src/init.c b/src/init.c index e90f0fb..8d963c5 100644 --- a/src/init.c +++ b/src/init.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -39,7 +38,6 @@ struct hyper_exec *global_exec; struct hyper_ctl ctl; -static struct hyper_event_ops hyper_signal_ops; static int hyper_handle_exit(struct hyper_pod *pod); static int hyper_stop_pod(struct hyper_pod *pod); @@ -212,38 +210,9 @@ static void pod_init_sigchld(int sig) hyper_handle_exit(NULL); } -static int hyper_signal_loop(struct hyper_event *de) +static void hyper_init_sigchld(int sig) { - int size; - struct signalfd_siginfo sinfo; - struct hyper_pod *pod = de->ptr; - - fprintf(stdout, "%s write to ctl tty fd\n", __func__); - - while (1) { - size = read(de->fd, &sinfo, sizeof(struct signalfd_siginfo)); - if (size <= 0) { - if (errno == EINTR) - continue; - if (errno == EAGAIN) - break; - - perror("fail to read signal fd"); - return -1; - } else if (size != sizeof(struct signalfd_siginfo)) { - perror("read signalfd siginfo failed"); - return -1; - } - - if (sinfo.ssi_signo != SIGCHLD) { - fprintf(stderr, "why give me signal %d?\n", sinfo.ssi_signo); - return 0; - } - - hyper_handle_exit(pod); - } - - return 0; + hyper_handle_exit(&global_pod); } struct hyper_pod_arg { @@ -258,7 +227,6 @@ static int hyper_pod_init(void *data) sigset_t mask; close(arg->ctl_pipe[0]); - close(ctl.sig.fd); close(ctl.efd); close(ctl.chan.fd); close(ctl.tty.fd); @@ -302,7 +270,6 @@ out: fail: hyper_send_type(arg->ctl_pipe[1], ERROR); close(arg->ctl_pipe[1]); - close(pod->sig.fd); goto out; } @@ -1204,16 +1171,27 @@ static struct hyper_event_ops hyper_ttyfd_ops = { .len_offset = 8, }; -static struct hyper_event_ops hyper_signal_ops = { - .read = hyper_signal_loop, - .hup = hyper_event_hup, -}; - static int hyper_loop(void) { int i, n; struct epoll_event *events; struct hyper_pod *pod = &global_pod; + sigset_t mask, omask; + + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); + + /* + * block SIGCHLD in the loop except when in the syscall of + * epoll_pwait(), it ensures that the SIGCHLD handling and + * the events handling are exclusive. + */ + if (sigprocmask(SIG_BLOCK, &mask, &omask) < 0) { + perror("sigprocmask SIGCHLD failed"); + return -1; + } + sigdelset(&omask, SIGCHLD); + signal(SIGCHLD, hyper_init_sigchld); ctl.efd = epoll_create1(EPOLL_CLOEXEC); if (ctl.efd < 0) { @@ -1235,17 +1213,10 @@ static int hyper_loop(void) return -1; } - fprintf(stdout, "hyper_init_event hyper signal event %p, ops %p, fd %d\n", - &ctl.sig, &hyper_signal_ops, ctl.sig.fd); - if (hyper_init_event(&ctl.sig, &hyper_signal_ops, pod) < 0 || - hyper_add_event(ctl.efd, &ctl.sig, EPOLLIN) < 0) { - return -1; - } - events = calloc(MAXEVENTS, sizeof(*events)); while (1) { - n = epoll_wait(ctl.efd, events, MAXEVENTS, -1); + n = epoll_pwait(ctl.efd, events, MAXEVENTS, -1, &omask); fprintf(stdout, "%s epoll_wait %d\n", __func__, n); if (n < 0) { @@ -1268,7 +1239,6 @@ static int hyper_loop(void) int main(int argc, char *argv[]) { char *cmdline, *ctl_serial, *tty_serial; - sigset_t mask; if (hyper_mkdir("/dev") < 0 || hyper_mkdir("/sys") < 0 || @@ -1326,20 +1296,6 @@ int main(int argc, char *argv[]) setenv("PATH", "/bin:/sbin/:/usr/bin/:/usr/sbin/", 1); - sigemptyset(&mask); - sigaddset(&mask, SIGCHLD); - - if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) { - perror("sigprocmask SIGCHLD failed"); - return -1; - } - - ctl.sig.fd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC); - if (ctl.sig.fd < 0) { - perror("create signalfd failed"); - return -1; - } - ctl.chan.fd = hyper_setup_ctl_channel(ctl_serial); if (ctl.chan.fd < 0) { fprintf(stderr, "fail to setup hyper control serial port\n"); @@ -1358,8 +1314,6 @@ int main(int argc, char *argv[]) out2: close(ctl.chan.fd); out1: - close(ctl.sig.fd); - free(cmdline); return 0;