[lxc-devel] [lxc/master] mainloop: capture output of short-lived init procs

brauner on Github lxc-bot at linuxcontainers.org
Mon Dec 25 14:04:08 UTC 2017


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 797 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20171225/eefd5d17/attachment.bin>
-------------- next part --------------
From 4a5f516dfecd869657764317b3e2d3cbd7ef88a4 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Mon, 25 Dec 2017 14:52:39 +0100
Subject: [PATCH 1/2] mainloop: add mainloop macros

This makes it clearer why handlers return what value.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/console.c  | 52 +++++++++++++++++++++++++++++++---------------------
 src/lxc/mainloop.c | 16 ++++++++--------
 src/lxc/mainloop.h |  3 +++
 src/lxc/start.h    |  2 +-
 4 files changed, 43 insertions(+), 30 deletions(-)

diff --git a/src/lxc/console.c b/src/lxc/console.c
index ad4a31405..e38d40dff 100644
--- a/src/lxc/console.c
+++ b/src/lxc/console.c
@@ -122,7 +122,7 @@ int lxc_console_cb_signal_fd(int fd, uint32_t events, void *cbdata,
 
 	if (siginfo.ssi_signo == SIGTERM) {
 		DEBUG("Received SIGTERM. Detaching from the console");
-		return 1;
+		return LXC_MAINLOOP_CLOSE;
 	}
 
 	if (siginfo.ssi_signo == SIGWINCH)
@@ -225,7 +225,7 @@ static int lxc_console_cb_con(int fd, uint32_t events, void *data,
 			return 0;
 		}
 		close(fd);
-		return 1;
+		return LXC_MAINLOOP_CLOSE;
 	}
 
 	if (fd == console->peer)
@@ -259,22 +259,30 @@ static int lxc_console_cb_con(int fd, uint32_t events, void *data,
 	return 0;
 }
 
-static void lxc_console_mainloop_add_peer(struct lxc_console *console)
+static int lxc_console_mainloop_add_peer(struct lxc_console *console)
 {
+	int ret;
+
 	if (console->peer >= 0) {
-		if (lxc_mainloop_add_handler(console->descr, console->peer,
-					     lxc_console_cb_con, console))
+		ret = lxc_mainloop_add_handler(console->descr, console->peer,
+					       lxc_console_cb_con, console);
+		if (ret < 0) {
 			WARN("Failed to add console peer handler to mainloop");
+			return -1;
+		}
 	}
 
-	if (console->tty_state && console->tty_state->sigfd != -1) {
-		if (lxc_mainloop_add_handler(console->descr,
-					     console->tty_state->sigfd,
-					     lxc_console_cb_signal_fd,
-					     console->tty_state)) {
-			WARN("Failed to add signal handler to mainloop");
-		}
+	if (!console->tty_state || console->tty_state->sigfd < 0)
+		return 0;
+
+	ret = lxc_mainloop_add_handler(console->descr, console->tty_state->sigfd,
+				       lxc_console_cb_signal_fd, console->tty_state);
+	if (ret < 0) {
+		WARN("Failed to add signal handler to mainloop");
+		return -1;
 	}
+
+	return 0;
 }
 
 extern int lxc_console_mainloop_add(struct lxc_epoll_descr *descr,
@@ -303,7 +311,9 @@ extern int lxc_console_mainloop_add(struct lxc_epoll_descr *descr,
 	 * does attach to it in lxc_console_allocate()
 	 */
 	console->descr = descr;
-	lxc_console_mainloop_add_peer(console);
+	ret = lxc_console_mainloop_add_peer(console);
+	if (ret < 0)
+		return -1;
 
 	return 0;
 }
@@ -794,10 +804,10 @@ int lxc_console_cb_tty_stdin(int fd, uint32_t events, void *cbdata,
 	char c;
 
 	if (fd != ts->stdinfd)
-		return 1;
+		return LXC_MAINLOOP_CLOSE;
 
 	if (lxc_read_nointr(ts->stdinfd, &c, 1) <= 0)
-		return 1;
+		return LXC_MAINLOOP_CLOSE;
 
 	if (ts->escape >= 1) {
 		/* we want to exit the console with Ctrl+a q */
@@ -807,13 +817,13 @@ int lxc_console_cb_tty_stdin(int fd, uint32_t events, void *cbdata,
 		}
 
 		if (c == 'q' && ts->saw_escape)
-			return 1;
+			return LXC_MAINLOOP_CLOSE;
 
 		ts->saw_escape = 0;
 	}
 
 	if (lxc_write_nointr(ts->masterfd, &c, 1) <= 0)
-		return 1;
+		return LXC_MAINLOOP_CLOSE;
 
 	return 0;
 }
@@ -826,17 +836,17 @@ int lxc_console_cb_tty_master(int fd, uint32_t events, void *cbdata,
 	int r, w;
 
 	if (fd != ts->masterfd)
-		return 1;
+		return LXC_MAINLOOP_CLOSE;
 
 	r = lxc_read_nointr(fd, buf, sizeof(buf));
 	if (r <= 0)
-		return 1;
+		return LXC_MAINLOOP_CLOSE;
 
 	w = lxc_write_nointr(ts->stdoutfd, buf, r);
 	if (w <= 0) {
-		return 1;
+		return LXC_MAINLOOP_CLOSE;
 	} else if (w != r) {
-		SYSERROR("failed to write");
+		SYSERROR("Failed to write");
 		return 1;
 	}
 
diff --git a/src/lxc/mainloop.c b/src/lxc/mainloop.c
index ab9c27dc0..19b98b790 100644
--- a/src/lxc/mainloop.c
+++ b/src/lxc/mainloop.c
@@ -40,12 +40,11 @@ struct mainloop_handler {
 
 int lxc_mainloop(struct lxc_epoll_descr *descr, int timeout_ms)
 {
-	int i, nfds;
+	int i, nfds, ret;
 	struct mainloop_handler *handler;
 	struct epoll_event events[MAX_EVENTS];
 
 	for (;;) {
-
 		nfds = epoll_wait(descr->epfd, events, MAX_EVENTS, timeout_ms);
 		if (nfds < 0) {
 			if (errno == EINTR)
@@ -53,14 +52,15 @@ int lxc_mainloop(struct lxc_epoll_descr *descr, int timeout_ms)
 			return -1;
 		}
 
+		ret = LXC_MAINLOOP_CONTINUE;
 		for (i = 0; i < nfds; i++) {
-			handler =
-				(struct mainloop_handler *) events[i].data.ptr;
+			handler = events[i].data.ptr;
 
-			/* If the handler returns a positive value, exit
-			   the mainloop */
-			if (handler->callback(handler->fd, events[i].events,
-					      handler->data, descr) > 0)
+			/* If the handler returns a positive value, exit the
+			 * mainloop. */
+			ret = handler->callback(handler->fd, events[i].events,
+						handler->data, descr);
+			if (ret == LXC_MAINLOOP_CLOSE)
 				return 0;
 		}
 
diff --git a/src/lxc/mainloop.h b/src/lxc/mainloop.h
index 46a820c66..ea53a012c 100644
--- a/src/lxc/mainloop.h
+++ b/src/lxc/mainloop.h
@@ -27,6 +27,9 @@
 #include <stdint.h>
 #include "list.h"
 
+#define LXC_MAINLOOP_CONTINUE 0
+#define LXC_MAINLOOP_CLOSE 1
+
 struct lxc_epoll_descr {
 	int epfd;
 	struct lxc_list handlers;
diff --git a/src/lxc/start.h b/src/lxc/start.h
index 498097b89..0e01c3cf0 100644
--- a/src/lxc/start.h
+++ b/src/lxc/start.h
@@ -138,5 +138,5 @@ extern int __lxc_start(const char *, struct lxc_handler *,
 		       struct lxc_operations *, void *, const char *, bool);
 
 extern int resolve_clone_flags(struct lxc_handler *handler);
-#endif
 
+#endif

From 4d0390517ceab246c7719c933d32a4eee804c4ec Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Mon, 25 Dec 2017 14:53:40 +0100
Subject: [PATCH 2/2] mainloop: capture output of short-lived init procs

The handler for the signal fd will detect when the init process of a container
has exited and cause the mainloop to close. However, this can happen before the
console handlers - or any other events for that matter - are handled. So in the
case of init exiting we still need to allow for all other pending events to be
handled before exiting. This allows us to capture output from short-lived init
processes.

Closes #1694.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/mainloop.c |  4 ++++
 src/lxc/mainloop.h |  1 +
 src/lxc/start.c    | 14 +++++++-------
 3 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/src/lxc/mainloop.c b/src/lxc/mainloop.c
index 19b98b790..3c966aa41 100644
--- a/src/lxc/mainloop.c
+++ b/src/lxc/mainloop.c
@@ -20,6 +20,7 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
+
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -69,6 +70,9 @@ int lxc_mainloop(struct lxc_epoll_descr *descr, int timeout_ms)
 
 		if (lxc_list_empty(&descr->handlers))
 			return 0;
+
+		if (ret == LXC_MAINLOOP_INIT_EXITED)
+			return 0;
 	}
 }
 
diff --git a/src/lxc/mainloop.h b/src/lxc/mainloop.h
index ea53a012c..8688df2a4 100644
--- a/src/lxc/mainloop.h
+++ b/src/lxc/mainloop.h
@@ -29,6 +29,7 @@
 
 #define LXC_MAINLOOP_CONTINUE 0
 #define LXC_MAINLOOP_CLOSE 1
+#define LXC_MAINLOOP_INIT_EXITED 2
 
 struct lxc_epoll_descr {
 	int epfd;
diff --git a/src/lxc/start.c b/src/lxc/start.c
index d70764fa1..0a690c81b 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -299,9 +299,9 @@ static int setup_signal_fd(sigset_t *oldmask)
 static int signal_handler(int fd, uint32_t events, void *data,
 			  struct lxc_epoll_descr *descr)
 {
-	struct signalfd_siginfo siginfo;
-	siginfo_t info;
 	int ret;
+	siginfo_t info;
+	struct signalfd_siginfo siginfo;
 	pid_t *pid = data;
 	bool init_died = false;
 
@@ -325,15 +325,15 @@ static int signal_handler(int fd, uint32_t events, void *data,
 	if (siginfo.ssi_signo != SIGCHLD) {
 		kill(*pid, siginfo.ssi_signo);
 		INFO("Forwarded signal %d to pid %d.", siginfo.ssi_signo, *pid);
-		return init_died ? 1 : 0;
+		return init_died ? LXC_MAINLOOP_INIT_EXITED : 0;
 	}
 
 	if (siginfo.ssi_code == CLD_STOPPED) {
 		INFO("Container init process was stopped.");
-		return init_died ? 1 : 0;
+		return init_died ? LXC_MAINLOOP_INIT_EXITED : 0;
 	} else if (siginfo.ssi_code == CLD_CONTINUED) {
 		INFO("Container init process was continued.");
-		return init_died ? 1 : 0;
+		return init_died ? LXC_MAINLOOP_INIT_EXITED : 0;
 	}
 
 	/* More robustness, protect ourself from a SIGCHLD sent
@@ -341,11 +341,11 @@ static int signal_handler(int fd, uint32_t events, void *data,
 	 */
 	if (siginfo.ssi_pid != *pid) {
 		NOTICE("Received SIGCHLD from pid %d instead of container init %d.", siginfo.ssi_pid, *pid);
-		return init_died ? 1 : 0;
+		return init_died ? LXC_MAINLOOP_INIT_EXITED : 0;
 	}
 
 	DEBUG("Container init process %d exited.", *pid);
-	return 1;
+	return LXC_MAINLOOP_INIT_EXITED;
 }
 
 static int lxc_serve_state_clients(const char *name,


More information about the lxc-devel mailing list