Commit 6a874d31 by Serge Hallyn

Merge pull request #953 from brauner/2016-04-08/lxc_attach_simplify_and_log

simplify pty allocation and implement pty logging
parents aa3ea4d3 da41561c
......@@ -27,10 +27,10 @@
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <lxc/lxccontainer.h>
......@@ -163,6 +163,9 @@ static int lxc_console_cb_con(int fd, uint32_t events, void *data,
char buf[1024];
int r,w;
if (events & EPOLLHUP)
return 1;
w = r = read(fd, buf, sizeof(buf));
if (r < 0) {
SYSERROR("failed to read");
......@@ -212,10 +215,9 @@ static void lxc_console_mainloop_add_peer(struct lxc_console *console)
}
}
int lxc_console_mainloop_add(struct lxc_epoll_descr *descr,
struct lxc_handler *handler)
extern int lxc_console_mainloop_add(struct lxc_epoll_descr *descr,
struct lxc_conf *conf)
{
struct lxc_conf *conf = handler->conf;
struct lxc_console *console = &conf->console;
if (conf->is_execute) {
......
......@@ -102,7 +102,7 @@ extern void lxc_console_free(struct lxc_conf *conf, int fd);
/*
* Register pty event handlers in an open mainloop
*/
extern int lxc_console_mainloop_add(struct lxc_epoll_descr *, struct lxc_handler *);
extern int lxc_console_mainloop_add(struct lxc_epoll_descr *, struct lxc_conf *);
/*
* Handle SIGWINCH events on the allocated ptys.
......
......@@ -64,6 +64,7 @@ static const struct option my_longopts[] = {
{"keep-env", no_argument, 0, 501},
{"keep-var", required_argument, 0, 502},
{"set-var", required_argument, 0, 'v'},
{"pty-log", required_argument, 0, 'L'},
LXC_COMMON_OPTIONS
};
......@@ -149,6 +150,9 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
return -1;
}
break;
case 'L':
args->console_log = arg;
break;
}
return 0;
......@@ -191,6 +195,8 @@ Options :\n\
--keep-env Keep all current environment variables. This\n\
is the current default behaviour, but is likely to\n\
change in the future.\n\
-L, --pty-log=FILE\n\
Log pty output to FILE\n\
-v, --set-var Set an additional variable that is seen by the\n\
attached program in the container. May be specified\n\
multiple times.\n\
......@@ -254,7 +260,10 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *
conf = c->lxc_conf;
free(conf->console.log_path);
conf->console.log_path = NULL;
if (my_args.console_log)
conf->console.log_path = strdup(my_args.console_log);
else
conf->console.log_path = NULL;
/* In the case of lxc-attach our peer pty will always be the current
* controlling terminal. We clear whatever was set by the user for
......@@ -272,39 +281,6 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *
if (lxc_console_create(conf) < 0)
return -1;
ts = conf->console.tty_state;
/*
* We need to make sure that the ouput that is produced inside the
* container is received on the host. Suppose we want to run
*
* lxc-attach -n a -- /bin/sh -c 'hostname >&2' > /dev/null
*
* This command produces output on stderr inside the container. On the
* host we close stdout by redirecting it to /dev/null. But stderr is,
* as expected, still connected to a tty. We receive the output produced
* on stderr in the container on stderr on the host.
*
* For the command
*
* lxc-attach -n a -- /bin/sh -c 'hostname >&2' 2> /dev/null
*
* the logic is analogous but because we now have closed stderr on the
* host no output will be received.
*
* Finally, imagine a more complicated case
*
* lxc-attach -n a -- /bin/sh -c 'echo OUT; echo ERR >&2' > /tmp/out 2> /tmp/err
*
* Here, we produce output in the container on stdout and stderr. On the
* host we redirect stdout and stderr to files. Because of that stdout
* and stderr are not dup2()ed. Thus, they are not connected to a pty
* and output on stdout and stderr is redirected to the corresponding
* files as expected.
*/
if (!isatty(STDOUT_FILENO) && isatty(STDERR_FILENO))
ts->stdoutfd = STDERR_FILENO;
else
ts->stdoutfd = STDOUT_FILENO;
conf->console.descr = &descr;
/* Shift ttys to container. */
......@@ -325,33 +301,8 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *
goto err2;
}
/* Register sigwinch handler in mainloop. When ts->sigfd == -1 it means
* we weren't able to install a sigwinch handler in
* lxc_console_create(). We don't consider this fatal and just move on.
*/
if (ts->sigfd != -1) {
ret = lxc_mainloop_add_handler(&descr, ts->sigfd,
lxc_console_cb_sigwinch_fd, ts);
if (ret) {
ERROR("failed to add handler for SIGWINCH fd");
goto err3;
}
}
/* Register i/o callbacks in mainloop. */
ret = lxc_mainloop_add_handler(&descr, ts->stdinfd,
lxc_console_cb_tty_stdin, ts);
if (ret) {
ERROR("failed to add handler for stdinfd");
goto err3;
}
ret = lxc_mainloop_add_handler(&descr, ts->masterfd,
lxc_console_cb_tty_master, ts);
if (ret) {
ERROR("failed to add handler for masterfd");
if (lxc_console_mainloop_add(&descr, conf) < 0)
goto err3;
}
ret = lxc_mainloop(&descr, -1);
if (ret) {
......
......@@ -365,7 +365,7 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
goto out_mainloop_open;
}
if (lxc_console_mainloop_add(&descr, handler)) {
if (lxc_console_mainloop_add(&descr, handler->conf)) {
ERROR("failed to add console handler to mainloop");
goto out_mainloop_open;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment