diff options
author | Lennart Poettering <lennart@poettering.net> | 2012-09-05 15:37:18 -0700 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2012-09-05 15:55:40 -0700 |
commit | cb7ec5645e0edf154f0cc8414f5914cb433d0dfe (patch) | |
tree | 8fa019e36d068cf16005e8327b46ee6d067bb9c0 /src | |
parent | 57371e5829a61e5ee6c9f98404dfc729d6c62608 (diff) |
shutdown: in containers, invoke reboot(2), too. Then fallback to exit() if CAP_SYS_BOOT is missing
The kernel's PID namespaces support reboot(2) just fine, so let's make
use of it if possible.
Diffstat (limited to 'src')
-rw-r--r-- | src/core/shutdown.c | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/src/core/shutdown.c b/src/core/shutdown.c index 558111b3d4..cc8c57bd2d 100644 --- a/src/core/shutdown.c +++ b/src/core/shutdown.c @@ -263,14 +263,8 @@ int main(int argc, char *argv[]) { arguments[2] = NULL; execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, arguments); - /* If we are in a container, just exit, this will kill our - * container for good. */ - if (in_container) { - log_error("Exiting container."); - exit(0); - } - - if (access("/run/initramfs/shutdown", X_OK) == 0) { + if (!in_container && + access("/run/initramfs/shutdown", X_OK) == 0) { if (prepare_new_root() >= 0 && pivot_to_new_root() >= 0) { @@ -280,25 +274,37 @@ int main(int argc, char *argv[]) { } if (cmd == LINUX_REBOOT_CMD_KEXEC) { - /* We cheat and exec kexec to avoid doing all its work */ - pid_t pid = fork(); - - if (pid < 0) - log_error("Could not fork: %m. Falling back to normal reboot."); - else if (pid > 0) { - wait_for_terminate_and_warn("kexec", pid); - log_warning("kexec failed. Falling back to normal reboot."); - } else { - /* Child */ - const char *args[3] = { "/sbin/kexec", "-e", NULL }; - execv(args[0], (char * const *) args); - return EXIT_FAILURE; + + if (!in_container) { + /* We cheat and exec kexec to avoid doing all its work */ + pid_t pid = fork(); + + if (pid < 0) + log_error("Could not fork: %m. Falling back to normal reboot."); + else if (pid > 0) { + wait_for_terminate_and_warn("kexec", pid); + log_warning("kexec failed. Falling back to normal reboot."); + } else { + /* Child */ + const char *args[3] = { "/sbin/kexec", "-e", NULL }; + execv(args[0], (char * const *) args); + return EXIT_FAILURE; + } } cmd = RB_AUTOBOOT; } reboot(cmd); + + if (errno == EPERM && in_container) { + /* If we are in a container, and we lacked + * CAP_SYS_BOOT just exit, this will kill our + * container for good. */ + log_error("Exiting container."); + exit(0); + } + log_error("Failed to invoke reboot(): %m"); r = -errno; |