[lxc-devel] [lxc/master] lxc-attach: ensure that oldtios is set

brauner on Github lxc-bot at linuxcontainers.org
Thu Feb 25 11:03:17 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 857 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20160225/3b189742/attachment.bin>
-------------- next part --------------
From f7bb32fc80b2de5837957a1f7aeac2982019feec Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Thu, 25 Feb 2016 11:57:11 +0100
Subject: [PATCH] lxc-attach: ensure that oldtios is set

Scenario:
	- lxc-attach to container with pty allocated inside of the container.
	- shutdown container
lxc-attach did not reset the terminal attributes to oldtios which caused
various problems and users had to call /usr/bin/reset. This patch ensures that
lxc-attach resets oldtios even in such cases.

Additionally, this commit makes the exit code in main() cleaner and most of
all, correct. Before we called lxc_container_put() before waitpid(). Let's do
it the other way around!

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 src/lxc/lxc_attach.c | 65 ++++++++++++++++++++++++++++++++++------------------
 1 file changed, 43 insertions(+), 22 deletions(-)

diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c
index 3439b2f..fcccb72 100644
--- a/src/lxc/lxc_attach.c
+++ b/src/lxc/lxc_attach.c
@@ -207,6 +207,7 @@ struct wrapargs {
 	lxc_attach_command_t *command;
 	struct lxc_tty_state *ts;
 	struct lxc_console *console;
+	struct termios *oldtios;
 	int ptyfd;
 };
 
@@ -286,16 +287,22 @@ static int pty_in_container(void *p)
 		return -1;
 	}
 
-	/* Get termios from one of the stdfds. */
-	struct termios oldtios;
-	ret = lxc_setup_tios(args->ptyfd, &oldtios);
-	if (ret < 0)
+	args->oldtios->c_iflag &= ~IGNBRK;
+	args->oldtios->c_iflag &= BRKINT;
+	args->oldtios->c_lflag &= ~(ECHO | ICANON | ISIG);
+	args->oldtios->c_cc[VMIN] = 1;
+	args->oldtios->c_cc[VTIME] = 0;
+
+	/* Set new termios. */
+	if (tcsetattr(args->ptyfd, TCSAFLUSH, args->oldtios)) {
+		ERROR("failed to set new terminal settings");
 		return -1;
+	}
 
 	/* Create master/slave fd pair for pty. */
 	pid = fork_pty(&master);
 	if (pid < 0)
-		goto err1;
+		return -1;
 
 	/* Pass windowsize from one of the stdfds to the current masterfd. */
 	lxc_console_winsz(args->ptyfd, master);
@@ -317,7 +324,7 @@ static int pty_in_container(void *p)
 	args->ts = lxc_console_sigwinch_init(args->ptyfd, master);
 	if (!args->ts) {
 		ret = -1;
-		goto err2;
+		goto err1;
 	}
 	args->ts->escape = -1;
 	args->ts->stdoutfd = STDOUT_FILENO;
@@ -327,7 +334,7 @@ static int pty_in_container(void *p)
 	ret = lxc_mainloop_open(&descr);
 	if (ret) {
 		ERROR("failed to create mainloop");
-		goto err3;
+		goto err2;
 	}
 
 	/* Register sigwinch handler in mainloop. */
@@ -335,7 +342,7 @@ static int pty_in_container(void *p)
 			lxc_console_cb_sigwinch_fd, args->ts);
 	if (ret) {
 		ERROR("failed to add handler for SIGWINCH fd");
-		goto err4;
+		goto err3;
 	}
 
 	/* Register i/o callbacks in mainloop. */
@@ -343,30 +350,28 @@ static int pty_in_container(void *p)
 			lxc_console_cb_tty_stdin, args->ts);
 	if (ret) {
 		ERROR("failed to add handler for stdinfd");
-		goto err4;
+		goto err3;
 	}
 
 	ret = lxc_mainloop_add_handler(&descr, args->ts->masterfd,
 			lxc_console_cb_tty_master, args->ts);
 	if (ret) {
 		ERROR("failed to add handler for masterfd");
-		goto err4;
+		goto err3;
 	}
 
 	ret = lxc_mainloop(&descr, -1);
 	if (ret) {
 		ERROR("mainloop returned an error");
-		goto err4;
+		goto err3;
 	}
 
-err4:
-	lxc_mainloop_close(&descr);
 err3:
-	lxc_console_sigwinch_fini(args->ts);
+	lxc_mainloop_close(&descr);
 err2:
-	close(args->ts->masterfd);
+	lxc_console_sigwinch_fini(args->ts);
 err1:
-	tcsetattr(args->ptyfd, TCSAFLUSH, &oldtios);
+	close(args->ts->masterfd);
 
 	ret = lxc_wait_for_pid_status(pid);
 	if (ret < 0)
@@ -537,6 +542,7 @@ int main(int argc, char *argv[])
 		wrap.command->argv = (char**)my_args.argv;
 	}
 
+	struct termios oldtios;
 	if (isatty(STDIN_FILENO) || isatty(STDOUT_FILENO) || isatty(STDERR_FILENO)) {
 		if (isatty(STDIN_FILENO))
 			wrap.ptyfd = STDIN_FILENO;
@@ -544,9 +550,19 @@ int main(int argc, char *argv[])
 			wrap.ptyfd = STDOUT_FILENO;
 		else if (isatty(STDERR_FILENO))
 			wrap.ptyfd = STDERR_FILENO;
+
+		/* Get current termios */
+		if (tcgetattr(wrap.ptyfd, &oldtios))
+			SYSERROR("failed to get current terminal settings");
+		wrap.oldtios = &oldtios;
+
+		/* Try to allocate pty in the container. */
 		ret = c->attach(c, pty_in_container, &wrap, &attach_options, &pid);
-		if (ret < 0)
+		if (ret < 0) {
+			wrap.oldtios = NULL;
+			/* Try to allocate pty on the host. */
 			ret = pty_on_host(c, &wrap, &pid);
+		}
 	} else {
 		if (my_args.argc > 1)
 			ret = c->attach(c, lxc_attach_run_command, &command, &attach_options, &pid);
@@ -554,17 +570,22 @@ int main(int argc, char *argv[])
 			ret = c->attach(c, lxc_attach_run_shell, NULL, &attach_options, &pid);
 	}
 
-	lxc_container_put(c);
-
 	if (ret < 0)
-		exit(EXIT_FAILURE);
+		goto out;
 
 	ret = lxc_wait_for_pid_status(pid);
 	if (ret < 0)
-		exit(EXIT_FAILURE);
+		goto out;
 
 	if (WIFEXITED(ret))
-		return WEXITSTATUS(ret);
+		ret = WEXITSTATUS(ret);
+
+out:
+	if (wrap.oldtios)
+		tcsetattr(wrap.ptyfd, TCSAFLUSH, &oldtios);
+	lxc_container_put(c);
 
+	if (ret >= 0)
+		exit(ret);
 	exit(EXIT_FAILURE);
 }


More information about the lxc-devel mailing list