mirror of
https://github.com/clearlinux/hyperstart.git
synced 2026-08-24 16:16:06 +00:00
Merge pull request #51 from laijs/pipes-stdio
use pipes for stdio when non tty
This commit is contained in:
+3
-2
@@ -567,8 +567,9 @@ fail:
|
||||
close(arg.pipe[0]);
|
||||
close(arg.pipe[1]);
|
||||
close(container->ns);
|
||||
hyper_reset_event(&container->exec.e);
|
||||
hyper_reset_event(&container->exec.errev);
|
||||
hyper_reset_event(&container->exec.stdinev);
|
||||
hyper_reset_event(&container->exec.stdoutev);
|
||||
hyper_reset_event(&container->exec.stderrev);
|
||||
container->ns = -1;
|
||||
fprintf(stdout, "container %s init exit code %d\n", container->id, -1);
|
||||
container->exec.code = -1;
|
||||
|
||||
+5
-3
@@ -230,10 +230,10 @@ int hyper_handle_event(int efd, struct epoll_event *event)
|
||||
__func__, event->events, de, de->fd, de->ops);
|
||||
|
||||
/* do not handle hup event if have in event */
|
||||
if (event->events & EPOLLIN) {
|
||||
if ((event->events & EPOLLIN) && de->ops->read) {
|
||||
fprintf(stdout, "%s event EPOLLIN, de %p, fd %d, %p\n",
|
||||
__func__, de, de->fd, de->ops);
|
||||
if (de->ops->read(de, efd) < 0)
|
||||
if (de->ops->read && de->ops->read(de, efd) < 0)
|
||||
return -1;
|
||||
} else if (event->events & EPOLLHUP) {
|
||||
fprintf(stdout, "%s event EPOLLHUP, de %p, fd %d, %p\n",
|
||||
@@ -252,7 +252,9 @@ int hyper_handle_event(int efd, struct epoll_event *event)
|
||||
|
||||
if (event->events & EPOLLERR) {
|
||||
fprintf(stderr, "get epoll err of not epool in event\n");
|
||||
return -1;
|
||||
if (de->ops->hup)
|
||||
de->ops->hup(de, efd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+133
-96
@@ -67,21 +67,11 @@ static int hyper_send_exec_code(struct hyper_exec *exec, int block) {
|
||||
return send_exec_finishing(exec->seq, 13, exec->code, block);
|
||||
}
|
||||
|
||||
static void pts_hup(struct hyper_event *de, int efd, int out)
|
||||
static void pts_hup(struct hyper_event *de, int efd, struct hyper_exec *exec)
|
||||
{
|
||||
struct hyper_exec *exec;
|
||||
struct hyper_pod *pod = de->ptr;
|
||||
uint64_t seq;
|
||||
|
||||
if (out) {
|
||||
exec = container_of(de, struct hyper_exec, e);
|
||||
seq = exec->seq;
|
||||
} else {
|
||||
exec = container_of(de, struct hyper_exec, errev);
|
||||
seq = exec->errseq;
|
||||
}
|
||||
|
||||
fprintf(stdout, "%s, seq %" PRIu64"\n", __func__, seq);
|
||||
fprintf(stdout, "%s, seq %" PRIu64"\n", __func__, exec->seq);
|
||||
|
||||
hyper_event_hup(de, efd);
|
||||
|
||||
@@ -90,19 +80,28 @@ static void pts_hup(struct hyper_event *de, int efd, int out)
|
||||
hyper_release_exec(exec, pod);
|
||||
}
|
||||
|
||||
static void stdin_hup(struct hyper_event *de, int efd)
|
||||
{
|
||||
struct hyper_exec *exec = container_of(de, struct hyper_exec, stdinev);
|
||||
fprintf(stdout, "%s\n", __func__);
|
||||
return pts_hup(de, efd, exec);
|
||||
}
|
||||
|
||||
static void stdout_hup(struct hyper_event *de, int efd)
|
||||
{
|
||||
struct hyper_exec *exec = container_of(de, struct hyper_exec, stdoutev);
|
||||
fprintf(stdout, "%s\n", __func__);
|
||||
return pts_hup(de, efd, 1);
|
||||
return pts_hup(de, efd, exec);
|
||||
}
|
||||
|
||||
static void stderr_hup(struct hyper_event *de, int efd)
|
||||
{
|
||||
struct hyper_exec *exec = container_of(de, struct hyper_exec, stderrev);
|
||||
fprintf(stdout, "%s\n", __func__);
|
||||
return pts_hup(de, efd, 0);
|
||||
return pts_hup(de, efd, exec);
|
||||
}
|
||||
|
||||
static int pts_loop(struct hyper_event *de, uint64_t seq, int efd, int out)
|
||||
static int pts_loop(struct hyper_event *de, uint64_t seq, int efd, struct hyper_exec *exec)
|
||||
{
|
||||
int size = -1;
|
||||
struct hyper_buf *buf = &ctl.tty.wbuf;
|
||||
@@ -122,7 +121,7 @@ static int pts_loop(struct hyper_event *de, uint64_t seq, int efd, int out)
|
||||
break;
|
||||
}
|
||||
if (size == 0) { // eof
|
||||
pts_hup(de, efd, out);
|
||||
pts_hup(de, efd, exec);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -139,28 +138,33 @@ static int pts_loop(struct hyper_event *de, uint64_t seq, int efd, int out)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stdout_loop(struct hyper_event *de, int efd)
|
||||
{
|
||||
struct hyper_exec *exec = container_of(de, struct hyper_exec, e);
|
||||
fprintf(stdout, "%s, seq %" PRIu64"\n", __func__, exec->seq);
|
||||
|
||||
return pts_loop(de, exec->seq, efd, 1);
|
||||
}
|
||||
|
||||
struct hyper_event_ops pts_ops = {
|
||||
.read = stdout_loop,
|
||||
.hup = stdout_hup,
|
||||
struct hyper_event_ops in_ops = {
|
||||
.hup = stdin_hup,
|
||||
.write = hyper_event_write,
|
||||
.wbuf_size = 512,
|
||||
};
|
||||
|
||||
static int stdout_loop(struct hyper_event *de, int efd)
|
||||
{
|
||||
struct hyper_exec *exec = container_of(de, struct hyper_exec, stdoutev);
|
||||
fprintf(stdout, "%s, seq %" PRIu64"\n", __func__, exec->seq);
|
||||
|
||||
return pts_loop(de, exec->seq, efd, exec);
|
||||
}
|
||||
|
||||
struct hyper_event_ops out_ops = {
|
||||
.read = stdout_loop,
|
||||
.hup = stdout_hup,
|
||||
/* don't need read buff, the pts data will store in tty buffer */
|
||||
/* don't need write buff, the stdout data is one way */
|
||||
};
|
||||
|
||||
static int stderr_loop(struct hyper_event *de, int efd)
|
||||
{
|
||||
struct hyper_exec *exec = container_of(de, struct hyper_exec, errev);
|
||||
struct hyper_exec *exec = container_of(de, struct hyper_exec, stderrev);
|
||||
fprintf(stdout, "%s, seq %" PRIu64"\n", __func__, exec->errseq);
|
||||
|
||||
return pts_loop(de, exec->errseq, efd, 0);
|
||||
return pts_loop(de, exec->errseq ? exec->errseq : exec->seq, efd, exec);
|
||||
}
|
||||
|
||||
struct hyper_event_ops err_ops = {
|
||||
@@ -170,13 +174,55 @@ struct hyper_event_ops err_ops = {
|
||||
/* don't need write buff, the stderr data is one way */
|
||||
};
|
||||
|
||||
static int hyper_setup_exec_notty(struct hyper_exec *e)
|
||||
{
|
||||
if (e->errseq == 0)
|
||||
return -1;
|
||||
|
||||
int inpipe[2];
|
||||
if (pipe2(inpipe, O_CLOEXEC) < 0) {
|
||||
fprintf(stderr, "creating stderr pipe failed\n");
|
||||
return -1;
|
||||
}
|
||||
hyper_setfd_nonblock(inpipe[1]);
|
||||
e->stdinev.fd = inpipe[1];
|
||||
e->stdinfd = inpipe[0];
|
||||
|
||||
int outpipe[2];
|
||||
if (pipe2(outpipe, O_CLOEXEC) < 0) {
|
||||
fprintf(stderr, "creating stderr pipe failed\n");
|
||||
return -1;
|
||||
}
|
||||
hyper_setfd_nonblock(outpipe[0]);
|
||||
e->stdoutev.fd = outpipe[0];
|
||||
e->stdoutfd = outpipe[1];
|
||||
|
||||
int errpipe[2];
|
||||
if (pipe2(errpipe, O_CLOEXEC) < 0) {
|
||||
fprintf(stderr, "creating stderr pipe failed\n");
|
||||
return -1;
|
||||
}
|
||||
hyper_setfd_nonblock(errpipe[0]);
|
||||
e->stderrev.fd = errpipe[0];
|
||||
e->stderrfd = errpipe[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hyper_setup_exec_tty(struct hyper_exec *e)
|
||||
{
|
||||
int unlock = 0;
|
||||
int ptymaster;
|
||||
char ptmx[512], path[512];
|
||||
|
||||
if (e->seq == 0)
|
||||
return 0;
|
||||
if (e->seq == 0) {
|
||||
e->ptyfd = open("/dev/null", O_RDWR | O_NOCTTY | O_CLOEXEC);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!e->tty) { // don't use tty for stdio
|
||||
return hyper_setup_exec_notty(e);
|
||||
}
|
||||
|
||||
if (e->errseq > 0) {
|
||||
int errpipe[2];
|
||||
@@ -185,20 +231,8 @@ int hyper_setup_exec_tty(struct hyper_exec *e)
|
||||
return -1;
|
||||
}
|
||||
hyper_setfd_nonblock(errpipe[0]);
|
||||
e->errev.fd = errpipe[0];
|
||||
e->errfd = errpipe[1];
|
||||
}
|
||||
|
||||
if (!e->tty) { // don't use tty for stdio
|
||||
int iopair[2];
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, iopair) < 0) {
|
||||
fprintf(stderr, "creating stdio pair failed\n");
|
||||
return -1;
|
||||
}
|
||||
hyper_setfd_nonblock(iopair[0]);
|
||||
e->e.fd = iopair[0];
|
||||
e->ptyfd = iopair[1];
|
||||
goto done;
|
||||
e->stderrev.fd = errpipe[0];
|
||||
e->stderrfd = errpipe[1];
|
||||
}
|
||||
|
||||
if (e->id) {
|
||||
@@ -218,18 +252,18 @@ int hyper_setup_exec_tty(struct hyper_exec *e)
|
||||
return -1;
|
||||
}
|
||||
|
||||
e->e.fd = open(ptmx, O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC);
|
||||
if (e->e.fd < 0) {
|
||||
ptymaster = open(ptmx, O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC);
|
||||
if (ptymaster < 0) {
|
||||
perror("open ptmx device for execcmd failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ioctl(e->e.fd, TIOCSPTLCK, &unlock) < 0) {
|
||||
if (ioctl(ptymaster, TIOCSPTLCK, &unlock) < 0) {
|
||||
perror("ioctl unlock ptmx device failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ioctl(e->e.fd, TIOCGPTN, &e->ptyno) < 0) {
|
||||
if (ioctl(ptymaster, TIOCGPTN, &e->ptyno) < 0) {
|
||||
perror("ioctl get execcmd pty device failed");
|
||||
return -1;
|
||||
}
|
||||
@@ -242,36 +276,29 @@ int hyper_setup_exec_tty(struct hyper_exec *e)
|
||||
e->ptyfd = open(ptmx, O_RDWR | O_NOCTTY | O_CLOEXEC);
|
||||
fprintf(stdout, "get pty device for exec %s\n", ptmx);
|
||||
|
||||
e->stdinev.fd = ptymaster;
|
||||
e->stdoutev.fd = dup(ptymaster);
|
||||
done:
|
||||
|
||||
e->stdinfd = e->ptyfd;
|
||||
e->stdoutfd = e->ptyfd;
|
||||
if (e->errseq == 0) {
|
||||
e->stderrev.fd = dup(e->stdoutev.fd);
|
||||
e->stderrfd = e->ptyfd;
|
||||
}
|
||||
fprintf(stdout, "%s pts event %p, fd %d %d\n",
|
||||
__func__, &e->e, e->e.fd, e->ptyfd);
|
||||
__func__, &e->stdinev, ptymaster, e->ptyfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hyper_dup_exec_tty(int to, struct hyper_exec *e)
|
||||
{
|
||||
int fd = -1, ret = -1;
|
||||
char pty[128];
|
||||
int ret = -1;
|
||||
|
||||
fprintf(stdout, "%s\n", __func__);
|
||||
setsid();
|
||||
|
||||
if (e->seq) {
|
||||
fd = e->ptyfd;
|
||||
} else {
|
||||
if (sprintf(pty, "/dev/null") < 0) {
|
||||
perror("get pts device name failed");
|
||||
goto out;
|
||||
}
|
||||
fd = open(pty, O_RDWR | O_NOCTTY);
|
||||
}
|
||||
|
||||
if (fd < 0) {
|
||||
perror("open pty device for execcmd failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (e->tty && (ioctl(fd, TIOCSCTTY, NULL) < 0)) {
|
||||
if (e->tty && (ioctl(e->ptyfd, TIOCSCTTY, NULL) < 0)) {
|
||||
perror("ioctl pty device for execcmd failed");
|
||||
goto out;
|
||||
}
|
||||
@@ -279,55 +306,50 @@ int hyper_dup_exec_tty(int to, struct hyper_exec *e)
|
||||
fflush(stdout);
|
||||
hyper_send_type(to, READY);
|
||||
|
||||
if (dup2(fd, STDIN_FILENO) < 0) {
|
||||
if (dup2(e->stdinfd, STDIN_FILENO) < 0) {
|
||||
perror("dup tty device to stdin failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dup2(fd, STDOUT_FILENO) < 0) {
|
||||
if (dup2(e->stdoutfd, STDOUT_FILENO) < 0) {
|
||||
perror("dup tty device to stdout failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (e->errseq > 0) {
|
||||
if (dup2(e->errfd, STDERR_FILENO) < 0) {
|
||||
perror("dup err pipe to stderr failed");
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if (dup2(fd, STDERR_FILENO) < 0) {
|
||||
perror("dup tty device to stderr failed");
|
||||
goto out;
|
||||
}
|
||||
if (dup2(e->stderrfd, STDERR_FILENO) < 0) {
|
||||
perror("dup err pipe to stderr failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
close(fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hyper_watch_exec_pty(struct hyper_exec *exec, struct hyper_pod *pod)
|
||||
{
|
||||
fprintf(stdout, "hyper_init_event container pts event %p, ops %p, fd %d\n",
|
||||
&exec->e, &pts_ops, exec->e.fd);
|
||||
&exec->stdinev, &in_ops, exec->stdinev.fd);
|
||||
|
||||
if (exec->seq == 0)
|
||||
return 0;
|
||||
|
||||
if (hyper_init_event(&exec->e, &pts_ops, pod) < 0 ||
|
||||
hyper_add_event(ctl.efd, &exec->e, EPOLLIN) < 0) {
|
||||
fprintf(stderr, "add container pts master event failed\n");
|
||||
if (hyper_init_event(&exec->stdinev, &in_ops, pod) < 0 ||
|
||||
hyper_add_event(ctl.efd, &exec->stdinev, EPOLLOUT) < 0) {
|
||||
fprintf(stderr, "add container stdin event failed\n");
|
||||
return -1;
|
||||
}
|
||||
exec->ref++;
|
||||
|
||||
if (exec->errseq == 0)
|
||||
return 0;
|
||||
if (hyper_init_event(&exec->stdoutev, &out_ops, pod) < 0 ||
|
||||
hyper_add_event(ctl.efd, &exec->stdoutev, EPOLLIN) < 0) {
|
||||
fprintf(stderr, "add container stdout event failed\n");
|
||||
return -1;
|
||||
}
|
||||
exec->ref++;
|
||||
|
||||
if (hyper_init_event(&exec->errev, &err_ops, pod) < 0 ||
|
||||
hyper_add_event(ctl.efd, &exec->errev, EPOLLIN) < 0) {
|
||||
if (hyper_init_event(&exec->stderrev, &err_ops, pod) < 0 ||
|
||||
hyper_add_event(ctl.efd, &exec->stderrev, EPOLLIN) < 0) {
|
||||
fprintf(stderr, "add container stderr event failed\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -578,8 +600,15 @@ out:
|
||||
return ret;
|
||||
close_tty:
|
||||
close(exec->ptyfd);
|
||||
close(exec->errfd);
|
||||
close(exec->e.fd);
|
||||
if (exec->stdinfd != exec->ptyfd)
|
||||
close(exec->stdinfd);
|
||||
if (exec->stdoutfd != exec->ptyfd)
|
||||
close(exec->stdoutfd);
|
||||
if (exec->stderrfd != exec->ptyfd)
|
||||
close(exec->stderrfd);
|
||||
close(exec->stdinev.fd);
|
||||
close(exec->stdoutev.fd);
|
||||
close(exec->stderrev.fd);
|
||||
free_exec:
|
||||
hyper_free_exec(exec);
|
||||
goto out;
|
||||
@@ -619,8 +648,9 @@ int hyper_release_exec(struct hyper_exec *exec,
|
||||
/* exec has no pty or the pty user already exited */
|
||||
fprintf(stdout, "last user of exec exit, release\n");
|
||||
|
||||
hyper_reset_event(&exec->e);
|
||||
hyper_reset_event(&exec->errev);
|
||||
hyper_reset_event(&exec->stdinev);
|
||||
hyper_reset_event(&exec->stdoutev);
|
||||
hyper_reset_event(&exec->stderrev);
|
||||
|
||||
list_del_init(&exec->list);
|
||||
|
||||
@@ -704,8 +734,15 @@ int hyper_handle_exec_exit(struct hyper_pod *pod, int pid, uint8_t code)
|
||||
|
||||
close(exec->ptyfd);
|
||||
exec->ptyfd = -1;
|
||||
close(exec->errfd);
|
||||
exec->errfd = -1;
|
||||
if (exec->stdinfd != exec->ptyfd)
|
||||
close(exec->stdinfd);
|
||||
exec->stdinfd = -1;
|
||||
if (exec->stdoutfd != exec->ptyfd)
|
||||
close(exec->stdoutfd);
|
||||
exec->stdoutfd = -1;
|
||||
if (exec->stderrfd != exec->ptyfd)
|
||||
close(exec->stderrfd);
|
||||
exec->stderrfd = -1;
|
||||
|
||||
hyper_release_exec(exec, pod);
|
||||
|
||||
|
||||
+6
-3
@@ -6,8 +6,9 @@
|
||||
|
||||
struct hyper_exec {
|
||||
struct list_head list;
|
||||
struct hyper_event e;
|
||||
struct hyper_event errev;
|
||||
struct hyper_event stdinev;
|
||||
struct hyper_event stdoutev;
|
||||
struct hyper_event stderrev;
|
||||
char *id;
|
||||
char **argv;
|
||||
int argc;
|
||||
@@ -18,7 +19,9 @@ struct hyper_exec {
|
||||
int ptyno;
|
||||
int init;
|
||||
int ptyfd;
|
||||
int errfd;
|
||||
int stdinfd;
|
||||
int stdoutfd;
|
||||
int stderrfd;
|
||||
uint8_t code;
|
||||
uint8_t exit;
|
||||
uint8_t ref;
|
||||
|
||||
+2
-2
@@ -1059,7 +1059,7 @@ static int hyper_ttyfd_handle(struct hyper_event *de, uint32_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
wbuf = &exec->e.wbuf;
|
||||
wbuf = &exec->stdinev.wbuf;
|
||||
|
||||
size = wbuf->size - wbuf->get;
|
||||
if (size == 0)
|
||||
@@ -1073,7 +1073,7 @@ static int hyper_ttyfd_handle(struct hyper_event *de, uint32_t len)
|
||||
if (size > 0) {
|
||||
memcpy(wbuf->data + wbuf->get, rbuf->data + 12, size);
|
||||
wbuf->get += size;
|
||||
if (hyper_modify_event(ctl.efd, &exec->e, EPOLLIN | EPOLLOUT) < 0) {
|
||||
if (hyper_modify_event(ctl.efd, &exec->stdinev, EPOLLOUT) < 0) {
|
||||
fprintf(stderr, "modify exec pts event to in & out failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
+12
-6
@@ -469,10 +469,13 @@ static int hyper_parse_container(struct hyper_pod *pod, struct hyper_container *
|
||||
|
||||
c->exec.init = 1;
|
||||
c->exec.code = -1;
|
||||
c->exec.e.fd = -1;
|
||||
c->exec.errev.fd = -1;
|
||||
c->exec.stdinev.fd = -1;
|
||||
c->exec.stdoutev.fd = -1;
|
||||
c->exec.stderrev.fd = -1;
|
||||
c->exec.ptyfd = -1;
|
||||
c->exec.errfd = -1;
|
||||
c->exec.stdinfd = -1;
|
||||
c->exec.stdoutfd = -1;
|
||||
c->exec.stderrfd = -1;
|
||||
c->ns = -1;
|
||||
INIT_LIST_HEAD(&c->list);
|
||||
|
||||
@@ -1027,9 +1030,12 @@ realloc:
|
||||
}
|
||||
|
||||
exec->ptyfd = -1;
|
||||
exec->errfd = -1;
|
||||
exec->e.fd = -1;
|
||||
exec->errev.fd = -1;
|
||||
exec->stdinfd = -1;
|
||||
exec->stdoutfd = -1;
|
||||
exec->stderrfd = -1;
|
||||
exec->stdinev.fd = -1;
|
||||
exec->stdoutev.fd = -1;
|
||||
exec->stderrev.fd = -1;
|
||||
INIT_LIST_HEAD(&exec->list);
|
||||
|
||||
for (i = 0, j = 0; i < n; i++) {
|
||||
|
||||
Reference in New Issue
Block a user