From: Daniel Lezcano Date: Thu, 8 Apr 2010 07:44:23 +0000 (+0200) Subject: restart the container at reboot X-Git-Tag: lxc-0.7.0~109 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=91480a0f0a62732f3115d556b689d62d574294ae;p=thirdparty%2Flxc.git restart the container at reboot When the reboot is detected, reboot the container. That needs to set all file descriptor opened by lxc-start to be flagged with the close-on-exec flag, otherwise when re-execing ourself, we inherit our own fd. Signed-off-by: Daniel Lezcano --- diff --git a/src/lxc/commands.c b/src/lxc/commands.c index 54e182603..7c24c8170 100644 --- a/src/lxc/commands.c +++ b/src/lxc/commands.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -232,6 +233,12 @@ extern int lxc_command_mainloop_add(const char *name, 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) { diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 3242f17b6..7747afc11 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -1089,12 +1089,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.path = NULL; new->console.peer = -1; new->console.master = -1; diff --git a/src/lxc/conf.h b/src/lxc/conf.h index 3a560fda3..d0232dbcc 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -183,6 +183,7 @@ struct lxc_conf { char *fstab; int tty; int pts; + int reboot; struct utsname *utsname; struct lxc_list cgroup; struct lxc_list network; diff --git a/src/lxc/confile.c b/src/lxc/confile.c index 80da62540..e44f2cda7 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -708,22 +708,34 @@ static int config_utsname(const char *key, char *value, struct lxc_conf *lxc_con 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'; @@ -738,10 +750,14 @@ static int parse_line(char *buffer, void *data) 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) diff --git a/src/lxc/lxc.h b/src/lxc/lxc.h index d89102fe3..a091baaeb 100644 --- a/src/lxc/lxc.h +++ b/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 diff --git a/src/lxc/lxc_start.c b/src/lxc/lxc_start.c index 37f9fd8c2..5cc03db04 100644 --- a/src/lxc/lxc_start.c +++ b/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; } diff --git a/src/lxc/mainloop.c b/src/lxc/mainloop.c index 7a8a941a5..986762cae 100644 --- a/src/lxc/mainloop.c +++ b/src/lxc/mainloop.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -132,6 +133,11 @@ int lxc_mainloop_open(struct lxc_epoll_descr *descr) if (descr->epfd < 0) return -1; + if (fcntl(descr->epfd, F_SETFD, FD_CLOEXEC)) { + close(descr->epfd); + return -1; + } + lxc_list_init(&descr->handlers); return 0; } diff --git a/src/lxc/start.c b/src/lxc/start.c index 0ce82371d..3b5023c9f 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -556,6 +556,9 @@ int lxc_start(const char *name, char *const argv[], struct lxc_conf *conf) 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); diff --git a/src/lxc/utmp.c b/src/lxc/utmp.c index 0c4e6f8cd..86cd5a00d 100644 --- a/src/lxc/utmp.c +++ b/src/lxc/utmp.c @@ -94,7 +94,8 @@ static int utmp_handler(int fd, void *data, struct lxc_epoll_descr *descr) } if (currun_level == '6') { - INFO("container has reboot"); + INFO("container has rebooted"); + conf->reboot = 1; kill(handler->pid, SIGKILL); } }