From 3fa27e7464bdaf0d854bc824d29a916d5c8b4dd8 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Tue, 8 Mar 2016 19:32:00 +0800 Subject: [PATCH 1/2] handle eof for the stdio handling Signed-off-by: Lai Jiangshan --- src/event.c | 4 ++-- src/event.h | 4 ++-- src/exec.c | 16 ++++++++++------ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/event.c b/src/event.c index 81b6375..c6dd3e0 100644 --- a/src/event.c +++ b/src/event.c @@ -107,7 +107,7 @@ static int hyper_getmsg_len(struct hyper_event *de, uint32_t *len) return 0; } -int hyper_event_read(struct hyper_event *de) +int hyper_event_read(struct hyper_event *de, int efd) { struct hyper_buf *buf = &de->rbuf; uint32_t len = 4; @@ -233,7 +233,7 @@ int hyper_handle_event(int efd, struct epoll_event *event) if (event->events & EPOLLIN) { fprintf(stdout, "%s event EPOLLIN, de %p, fd %d, %p\n", __func__, de, de->fd, de->ops); - if (de->ops->read(de) < 0) + if (de->ops->read(de, efd) < 0) return -1; } else if (event->events & EPOLLHUP) { fprintf(stdout, "%s event EPOLLHUP, de %p, fd %d, %p\n", diff --git a/src/event.h b/src/event.h index 9096693..a2c6150 100644 --- a/src/event.h +++ b/src/event.h @@ -7,7 +7,7 @@ struct hyper_event; struct hyper_event_ops { - int (*read)(struct hyper_event *e); + int (*read)(struct hyper_event *e, int efd); int (*write)(struct hyper_event *e); int (*handle)(struct hyper_event *e, uint32_t len); void (*hup)(struct hyper_event *e, int efd); @@ -39,6 +39,6 @@ int hyper_init_event(struct hyper_event *de, struct hyper_event_ops *ops, int hyper_handle_event(int efd, struct epoll_event *event); void hyper_reset_event(struct hyper_event *de); void hyper_event_hup(struct hyper_event *de, int efd); -int hyper_event_read(struct hyper_event *de); +int hyper_event_read(struct hyper_event *dei, int efd); int hyper_event_write(struct hyper_event *de); #endif diff --git a/src/exec.c b/src/exec.c index 84e4725..bdb1cd8 100644 --- a/src/exec.c +++ b/src/exec.c @@ -101,7 +101,7 @@ static void stderr_hup(struct hyper_event *de, int efd) return pts_hup(de, efd, 0); } -static int pts_loop(struct hyper_event *de, uint64_t seq) +static int pts_loop(struct hyper_event *de, uint64_t seq, int efd, int out) { int size = -1; struct hyper_buf *buf = &ctl.tty.wbuf; @@ -109,7 +109,7 @@ static int pts_loop(struct hyper_event *de, uint64_t seq) while ((buf->get + 12 < buf->size) && size) { size = read(de->fd, buf->data + buf->get + 12, buf->size - buf->get - 12); fprintf(stdout, "%s: read %d data\n", __func__, size); - if (size <= 0) { + if (size < 0) { if (errno == EINTR) continue; @@ -120,6 +120,10 @@ static int pts_loop(struct hyper_event *de, uint64_t seq) break; } + if (size == 0) { // eof + pts_hup(de, efd, out); + break; + } hyper_set_be64(buf->data + buf->get, seq); hyper_set_be32(buf->data + buf->get + 8, size + 12); @@ -134,12 +138,12 @@ static int pts_loop(struct hyper_event *de, uint64_t seq) return 0; } -static int stdout_loop(struct hyper_event *de) +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); + return pts_loop(de, exec->seq, efd, 1); } struct hyper_event_ops pts_ops = { @@ -150,12 +154,12 @@ struct hyper_event_ops pts_ops = { /* don't need read buff, the pts data will store in tty buffer */ }; -static int stderr_loop(struct hyper_event *de) +static int stderr_loop(struct hyper_event *de, int efd) { struct hyper_exec *exec = container_of(de, struct hyper_exec, errev); fprintf(stdout, "%s, seq %" PRIu64"\n", __func__, exec->errseq); - return pts_loop(de, exec->errseq); + return pts_loop(de, exec->errseq, efd, 0); } struct hyper_event_ops err_ops = { From e12e480f79b64aa904b6b1b51a4dd04884be2a34 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Sun, 6 Mar 2016 20:31:21 +0800 Subject: [PATCH 2/2] change VmContainer's stdio's protocal VmContainer.Tty: allocate tty or not VmContainer.Stdio: Stdio sequence number VmContainer.Stderr: Stderr sequence number if stderr is not share with stdout (currently used when VmContainer.Tty is false) And new stdio allocation code which respects the VmContainer.Tty. Signed-off-by: Lai Jiangshan --- src/exec.c | 16 +++++++++++++++- src/exec.h | 1 + src/parse.c | 8 ++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/exec.c b/src/exec.c index bdb1cd8..eb4d483 100644 --- a/src/exec.c +++ b/src/exec.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -188,6 +189,18 @@ int hyper_setup_exec_tty(struct hyper_exec *e) 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; + } + if (e->id) { if (sprintf(path, "/tmp/hyper/%s/devpts/", e->id) < 0) { fprintf(stderr, "get ptmx path failed\n"); @@ -229,6 +242,7 @@ 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); +done: fprintf(stdout, "%s pts event %p, fd %d %d\n", __func__, &e->e, e->e.fd, e->ptyfd); return 0; @@ -257,7 +271,7 @@ int hyper_dup_exec_tty(int to, struct hyper_exec *e) goto out; } - if (e->seq && (ioctl(fd, TIOCSCTTY, NULL) < 0)) { + if (e->tty && (ioctl(fd, TIOCSCTTY, NULL) < 0)) { perror("ioctl pty device for execcmd failed"); goto out; } diff --git a/src/exec.h b/src/exec.h index 56320ca..97cb986 100644 --- a/src/exec.h +++ b/src/exec.h @@ -11,6 +11,7 @@ struct hyper_exec { char *id; char **argv; int argc; + int tty; // use tty or not uint64_t seq; uint64_t errseq; int pid; diff --git a/src/parse.c b/src/parse.c index 5500929..fc529f6 100644 --- a/src/parse.c +++ b/src/parse.c @@ -497,6 +497,14 @@ static int hyper_parse_container(struct hyper_pod *pod, struct hyper_container * fprintf(stdout, "container rootfs %s\n", c->rootfs); i++; } else if (json_token_streq(json, t, "tty") && t->size == 1) { + if (!json_token_streq(json, &toks[++i], "false")) { + c->exec.tty = 1; + fprintf(stdout, "container uses terminal\n"); + } else { + fprintf(stdout, "container doesn't use terminal\n"); + } + i++; + } else if (json_token_streq(json, t, "stdio") && t->size == 1) { c->exec.seq = json_token_ll(json, &toks[++i]); fprintf(stdout, "container seq %" PRIu64 "\n", c->exec.seq); i++;