mirror of
https://github.com/clearlinux/hyperstart.git
synced 2026-09-03 20:21:47 +00:00
Merge pull request #48 from laijs/sigchld
Simplify SIGCHLD handling and make it exclusive with event handling
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
+26
-116
@@ -15,7 +15,6 @@
|
||||
#include <limits.h>
|
||||
#include <mntent.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/signalfd.h>
|
||||
#include <inttypes.h>
|
||||
#include <ctype.h>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -207,79 +205,14 @@ static int hyper_handle_exit(struct hyper_pod *pod)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hyper_signal_loop(struct hyper_event *de)
|
||||
static void pod_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(NULL);
|
||||
}
|
||||
|
||||
static int pod_init_loop(struct hyper_pod *pod)
|
||||
static void hyper_init_sigchld(int sig)
|
||||
{
|
||||
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;
|
||||
hyper_handle_exit(&global_pod);
|
||||
}
|
||||
|
||||
struct hyper_pod_arg {
|
||||
@@ -294,26 +227,17 @@ 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);
|
||||
|
||||
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,15 +262,14 @@ 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);
|
||||
|
||||
fail:
|
||||
hyper_send_type(arg->ctl_pipe[1], ERROR);
|
||||
close(arg->ctl_pipe[1]);
|
||||
close(pod->sig.fd);
|
||||
|
||||
goto out;
|
||||
}
|
||||
@@ -1248,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) {
|
||||
@@ -1279,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) {
|
||||
@@ -1312,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 ||
|
||||
@@ -1370,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");
|
||||
@@ -1402,8 +1314,6 @@ int main(int argc, char *argv[])
|
||||
out2:
|
||||
close(ctl.chan.fd);
|
||||
out1:
|
||||
close(ctl.sig.fd);
|
||||
|
||||
free(cmdline);
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user