When the reboot is detected, reboot the container.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
---
 src/lxc/commands.c  |    7 +++++++
 src/lxc/conf.c      |    6 ------
 src/lxc/conf.h      |    1 +
 src/lxc/confile.c   |   30 +++++++++++++++++++++++-------
 src/lxc/lxc.h       |    3 ++-
 src/lxc/lxc_start.c |   19 ++++++++++++++-----
 src/lxc/start.c     |    3 +++
 src/lxc/utmp.c      |    3 ++-
 8 files changed, 52 insertions(+), 20 deletions(-)

Index: lxc/src/lxc/commands.c
===================================================================
--- lxc.orig/src/lxc/commands.c
+++ lxc/src/lxc/commands.c
@@ -25,6 +25,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include <signal.h>
+#include <fcntl.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <sys/poll.h>
@@ -228,6 +229,12 @@ extern int lxc_command_mainloop_add(cons
 		return -1;
 	}
 
+	if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
+		SYSERROR("failed to set sigfd to close-on-exec");
+		close(fd);
+		return -1;
+	}
+
 	ret = lxc_mainloop_add_handler(descr, fd, incoming_command_handler, handler);
 	if (ret) {
 		ERROR("failed to add handler for command socket");
Index: lxc/src/lxc/lxc.h
===================================================================
--- lxc.orig/src/lxc/lxc.h
+++ lxc/src/lxc/lxc.h
@@ -43,9 +43,10 @@ struct lxc_conf;
  * Start the specified command inside a container
  * @name     : the name of the container
  * @argv     : an array of char * corresponding to the commande line
+ * @conf     : configuration
  * Returns 0 on sucess, < 0 otherwise
  */
-extern int lxc_start(const char *name, char *const argv[], struct lxc_conf *);
+extern int lxc_start(const char *name, char *const argv[], struct lxc_conf *conf);
 
 /*
  * Stop the container previously started with lxc_start, all
Index: lxc/src/lxc/lxc_start.c
===================================================================
--- lxc.orig/src/lxc/lxc_start.c
+++ lxc/src/lxc/lxc_start.c
@@ -90,17 +90,15 @@ Options :\n\
 
 int main(int argc, char *argv[])
 {
-	char *const *args;
 	int err = -1;
-
+	struct lxc_conf *conf;
+	char *const *args;
+	char *rcfile = NULL;
 	char *const default_args[] = {
 		"/sbin/init",
 		'\0',
 	};
 
-	char *rcfile = NULL;
-	struct lxc_conf *conf;
-
 	lxc_list_init(&defines);
 
 	if (lxc_arguments_parse(&my_args, argc, argv))
@@ -176,6 +174,17 @@ int main(int argc, char *argv[])
 
 	err = lxc_start(my_args.name, args, conf);
 
+	/*
+	 * exec ourself, that requires to have all opened fd
+	 * with the close-on-exec flag set
+	 */
+	if (conf->reboot) {
+		INFO("rebooting container");
+		execvp(argv[0], argv);
+		SYSERROR("failed to exec");
+		err = -1;
+	}
+
 	return err;
 }
 
Index: lxc/src/lxc/start.c
===================================================================
--- lxc.orig/src/lxc/start.c
+++ lxc/src/lxc/start.c
@@ -471,6 +471,9 @@ int lxc_start(const char *name, char *co
 	while (waitpid(handler->pid, &status, 0) < 0 && errno == EINTR)
 		continue;
 
+	if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL))
+		WARN("failed to restore sigprocmask");
+
 	err =  lxc_error_set_and_log(handler->pid, status);
 out_fini:
 	lxc_fini(name, handler);
Index: lxc/src/lxc/utmp.c
===================================================================
--- lxc.orig/src/lxc/utmp.c
+++ lxc/src/lxc/utmp.c
@@ -94,7 +94,8 @@ static int utmp_handler(int fd, void *da
 		}
 
 		if (currun_level == '6') {
-			INFO("container has reboot");
+			INFO("container has rebooted");
+			conf->reboot = 1;
 			kill(handler->pid, SIGKILL);
 		}
 	}
Index: lxc/src/lxc/conf.c
===================================================================
--- lxc.orig/src/lxc/conf.c
+++ lxc/src/lxc/conf.c
@@ -1068,12 +1068,6 @@ struct lxc_conf *lxc_conf_init(void)
 	}
 	memset(new, 0, sizeof(*new));
 
-	new->rootfs = NULL;
-	new->pivotdir = NULL;
-	new->fstab = NULL;
-	new->utsname = NULL;
-	new->tty = 0;
-	new->pts = 0;
 	new->console.peer = -1;
 	new->console.master = -1;
 	new->console.slave = -1;
Index: lxc/src/lxc/conf.h
===================================================================
--- lxc.orig/src/lxc/conf.h
+++ lxc/src/lxc/conf.h
@@ -181,6 +181,7 @@ struct lxc_conf {
 	char *fstab;
 	int tty;
 	int pts;
+	int reboot;
 	struct utsname *utsname;
 	struct lxc_list cgroup;
 	struct lxc_list network;
Index: lxc/src/lxc/confile.c
===================================================================
--- lxc.orig/src/lxc/confile.c
+++ lxc/src/lxc/confile.c
@@ -692,22 +692,34 @@ static int config_utsname(const char *ke
 static int parse_line(char *buffer, void *data)
 {
 	struct config *config;
-	char *line = buffer;
+	char *line;
 	char *dot;
 	char *key;
 	char *value;
+	int ret = -1;
 
-	if (lxc_is_line_empty(line))
+	if (lxc_is_line_empty(buffer))
 		return 0;
 
+	/* we have to dup the buffer otherwise, at the re-exec for reboot we modified
+	 * the original string on the stack by replacing '=' by '\0' below
+	 */
+	line = strdup(buffer);
+	if (!line) {
+		SYSERROR("failed to allocate memory for '%s'", buffer);
+		goto out;
+	}
+
 	line += lxc_char_left_gc(line, strlen(line));
-	if (line[0] == '#')
-		return 0;
+	if (line[0] == '#') {
+		ret = 0;
+		goto out;
+	}
 
 	dot = strstr(line, "=");
 	if (!dot) {
 		ERROR("invalid configuration line: %s", line);
-		return -1;
+		goto out;
 	}
 
 	*dot = '\0';
@@ -722,10 +734,14 @@ static int parse_line(char *buffer, void
 	config = getconfig(key);
 	if (!config) {
 		ERROR("unknow key %s", key);
-		return -1;
+		goto out;
 	}
 
-	return config->cb(key, value, data);
+	ret = config->cb(key, value, data);
+
+out:
+	free(line);
+	return ret;
 }
 
 int lxc_config_readline(char *buffer, struct lxc_conf *conf)



