summaryrefslogtreecommitdiff
path: root/src/core/shutdown.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2012-09-05 15:37:18 -0700
committerLennart Poettering <lennart@poettering.net>2012-09-05 15:55:40 -0700
commitcb7ec5645e0edf154f0cc8414f5914cb433d0dfe (patch)
tree8fa019e36d068cf16005e8327b46ee6d067bb9c0 /src/core/shutdown.c
parent57371e5829a61e5ee6c9f98404dfc729d6c62608 (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/core/shutdown.c')
-rw-r--r--src/core/shutdown.c48
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;