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..eb4d483 100644 --- a/src/exec.c +++ b/src/exec.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -101,7 +102,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 +110,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 +121,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 +139,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 +155,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 = { @@ -184,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"); @@ -225,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; @@ -253,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++;