]> git.proxmox.com Git - mirror_lxc.git/commitdiff
support proper container reboot
authorSerge Hallyn <serge.hallyn@canonical.com>
Wed, 25 Jan 2012 04:05:28 +0000 (22:05 -0600)
committerDaniel Lezcano <daniel.lezcano@free.fr>
Sun, 26 Feb 2012 09:44:40 +0000 (10:44 +0100)
This patch looks for Daniel's kernel patch allowing the lxc monitor
to tell container reboot from shutdown based on the exit signal.  If
that patch is not there, utmp monitoring is used.  Otherwise, it only
looks for the signal.  Note that the 'conf->need_utmp_watch' is
technically not necessary, as there is no harm in watching the utmp
file.

Signed-off-by: Serge Hallyn <serge.hallyn@canonical.com>
Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
src/lxc/conf.h
src/lxc/start.c

index 973f694c7adcd8655c161f07069d23140353fd11..eff1828f896f7f517e578180efc6c8abbac614c2 100644 (file)
@@ -203,6 +203,7 @@ struct lxc_conf {
        int tty;
        int pts;
        int reboot;
+       int need_utmp_watch;
        int personality;
        struct utsname *utsname;
        struct lxc_list cgroup;
index 2c92a17a7abea986029fc193878428fdc54e3bc9..eb7d01f9b3306de22408ad64fb2524c2697a9970 100644 (file)
@@ -303,9 +303,11 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
                goto out_mainloop_open;
        }
 
-       if (lxc_utmp_mainloop_add(&descr, handler)) {
-               ERROR("failed to add utmp handler to mainloop");
-               goto out_mainloop_open;
+       if (handler->conf->need_utmp_watch) {
+               if (lxc_utmp_mainloop_add(&descr, handler)) {
+                       ERROR("failed to add utmp handler to mainloop");
+                       goto out_mainloop_open;
+               }
        }
 
        return lxc_mainloop(&descr);
@@ -402,6 +404,28 @@ void lxc_abort(const char *name, struct lxc_handler *handler)
                kill(handler->pid, SIGKILL);
 }
 
+#include <sys/reboot.h>
+#include <linux/reboot.h>
+
+static int must_drop_cap_sys_boot(void)
+{
+       FILE *f = fopen("/proc/sys/kernel/ctrl-alt-del", "r");
+       int ret;
+       int v;
+
+       if (!f)
+               return 1;
+
+       ret = fscanf(f, "%d", &v);
+       fclose(f);
+       if (ret != 1)
+               return 1;
+       ret = reboot(v ? LINUX_REBOOT_CMD_CAD_ON : LINUX_REBOOT_CMD_CAD_OFF);
+       if (ret != -1)
+               return 1;
+       return 0;
+}
+
 static int do_start(void *data)
 {
        struct lxc_handler *handler = data;
@@ -436,10 +460,14 @@ static int do_start(void *data)
                goto out_warn_father;
        }
 
-       if (prctl(PR_CAPBSET_DROP, CAP_SYS_BOOT, 0, 0, 0)) {
-               SYSERROR("failed to remove CAP_SYS_BOOT capability");
-               return -1;
-       }
+       if (must_drop_cap_sys_boot()) {
+               if (prctl(PR_CAPBSET_DROP, CAP_SYS_BOOT, 0, 0, 0)) {
+                       SYSERROR("failed to remove CAP_SYS_BOOT capability");
+                       return -1;
+               }
+               handler->conf->need_utmp_watch = 1;
+       } else
+               handler->conf->need_utmp_watch = 0;
 
        close(handler->sigfd);
 
@@ -570,6 +598,24 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
        while (waitpid(handler->pid, &status, 0) < 0 && errno == EINTR)
                continue;
 
+        if (!WIFSIGNALED(status)) {
+                printf("child process exited but was not signaled\n");
+                return -1;
+        }
+
+       switch(WTERMSIG(status)) {
+       case SIGINT: /* halt */
+               DEBUG("Container halting");
+               break;
+       case SIGHUP: /* reboot */
+               DEBUG("Container rebooting");
+               handler->conf->reboot = 1;
+               break;
+       default:
+               DEBUG("unknown exit status for init: %d\n", WTERMSIG(status));
+               break;
+        }
+
        err =  lxc_error_set_and_log(handler->pid, status);
 out_fini:
        lxc_cgroup_destroy(name);
@@ -618,5 +664,6 @@ int lxc_start(const char *name, char *const argv[], struct lxc_conf *conf)
        if (lxc_check_inherited(-1))
                return -1;
 
+       conf->need_utmp_watch = 1;
        return __lxc_start(name, conf, &start_ops, &start_arg);
 }