[lxc-devel] [lxc/master] simplify pty allocation and implement pty logging

brauner on Github lxc-bot at linuxcontainers.org
Fri Apr 8 14:02:43 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 792 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20160408/02a33659/attachment.bin>
-------------- next part --------------
From da41561c72067a5e109e8c5482dbeb4131641dc2 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Fri, 8 Apr 2016 15:53:36 +0200
Subject: [PATCH] simplify pty allocation and implement pty logging

lxc-attach allocated a pty in a manner that relied on ts->stdinfd and
ts->stdoutfd to be set. We had to resort to a trick to get it working when
output is redirected. The new implementation gets rid of the black magic and
also simplifies the code.

This commit also implements pty logging for lxc-attach. Users will now be able
to log commands and corresponding output to a file given that lxc-attach
allocates a pty.

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 src/lxc/console.c    | 12 +++++----
 src/lxc/console.h    |  2 +-
 src/lxc/lxc_attach.c | 71 ++++++++--------------------------------------------
 src/lxc/start.c      |  2 +-
 4 files changed, 20 insertions(+), 67 deletions(-)

diff --git a/src/lxc/console.c b/src/lxc/console.c
index 2ce3cc4..f874172 100644
--- a/src/lxc/console.c
+++ b/src/lxc/console.c
@@ -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) {
diff --git a/src/lxc/console.h b/src/lxc/console.h
index d3ccd8b..fefdb19 100644
--- a/src/lxc/console.h
+++ b/src/lxc/console.h
@@ -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.
diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c
index cdc56d6..f02ef26 100644
--- a/src/lxc/lxc_attach.c
+++ b/src/lxc/lxc_attach.c
@@ -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) {
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 5be0077..d9d5814 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -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;
 	}


More information about the lxc-devel mailing list