nspawn: handle poweroff/reboot nicely in containers

This commit is contained in:
Lennart Poettering 2012-09-05 16:23:41 -07:00
parent cb7ec5645e
commit d87be9b0af
4 changed files with 233 additions and 197 deletions

7
TODO
View File

@ -49,15 +49,16 @@ Bugfixes:
Features:
* Query Paul Moore about relabelling socket fds while they are open
* log fewer journal internal messages to the kernel kmsg
* move keymaps to /usr/lib/... rather than /usr/lib/udev/...
* journald: check whether it is OK if the client can still modify delivered journal entries
* json: use yajl
* json: don't add wrapping array, just put entries on one line each
* json: add -o json-pretty in addition to -o json, make the latter output one line per entry
* json: use jensson
* json: properly serialize multiple fields with the same name per entry
* journalctl: make -l the default

View File

@ -232,7 +232,7 @@
CAP_SETUID, CAP_SYS_ADMIN,
CAP_SYS_CHROOT, CAP_SYS_NICE,
CAP_SYS_PTRACE, CAP_SYS_TTY_CONFIG,
CAP_SYS_RESOURCE.</para></listitem>
CAP_SYS_RESOURCE, CAP_SYS_BOOT.</para></listitem>
</varlistentry>
<varlistentry>

View File

@ -92,7 +92,8 @@ static uint64_t arg_retain =
(1ULL << CAP_SYS_NICE) |
(1ULL << CAP_SYS_PTRACE) |
(1ULL << CAP_SYS_TTY_CONFIG) |
(1ULL << CAP_SYS_RESOURCE);
(1ULL << CAP_SYS_RESOURCE) |
(1ULL << CAP_SYS_BOOT);
static int help(void) {
@ -1167,11 +1168,6 @@ int main(int argc, char *argv[]) {
cfmakeraw(&raw_attr);
raw_attr.c_lflag &= ~ECHO;
if (tcsetattr(STDIN_FILENO, TCSANOW, &raw_attr) < 0) {
log_error("Failed to set terminal attributes: %m");
goto finish;
}
if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, kmsg_socket_pair) < 0) {
log_error("Failed to create kmsg socket pair");
goto finish;
@ -1181,6 +1177,14 @@ int main(int argc, char *argv[]) {
sigset_add_many(&mask, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, -1);
assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
for (;;) {
siginfo_t status;
if (tcsetattr(STDIN_FILENO, TCSANOW, &raw_attr) < 0) {
log_error("Failed to set terminal attributes: %m");
goto finish;
}
pid = syscall(__NR_clone, SIGCHLD|CLONE_NEWIPC|CLONE_NEWNS|CLONE_NEWPID|CLONE_NEWUTS|(arg_private_network ? CLONE_NEWNET : 0), NULL);
if (pid < 0) {
if (errno == EINVAL)
@ -1398,15 +1402,46 @@ int main(int argc, char *argv[]) {
if (process_pty(master, &mask) < 0)
goto finish;
if (saved_attr_valid) {
if (saved_attr_valid)
tcsetattr(STDIN_FILENO, TCSANOW, &saved_attr);
saved_attr_valid = false;
r = wait_for_terminate(pid, &status);
if (r < 0) {
r = EXIT_FAILURE;
break;
}
r = wait_for_terminate_and_warn(argc > optind ? argv[optind] : "bash", pid);
if (status.si_code == CLD_EXITED) {
if (status.si_status != 0) {
log_error("Container failed with error code %i.", status.si_status);
r = status.si_status;
break;
}
if (r < 0)
log_debug("Container exited successfully.");
break;
} else if (status.si_code == CLD_KILLED &&
status.si_status == SIGINT) {
log_info("Container has been shut down.");
r = 0;
break;
} else if (status.si_code == CLD_KILLED &&
status.si_status == SIGHUP) {
log_info("Container is being rebooted.");
continue;
} else if (status.si_code == CLD_KILLED ||
status.si_code == CLD_DUMPED) {
log_error("Container terminated by signal %s.", signal_to_string(status.si_status));
r = EXIT_FAILURE;
break;
} else {
log_error("Container failed due to unknown reason.");
r = EXIT_FAILURE;
break;
}
}
finish:
if (saved_attr_valid)

View File

@ -4011,7 +4011,8 @@ int wait_for_terminate_and_warn(const char *name, pid_t pid) {
assert(name);
assert(pid > 1);
if ((r = wait_for_terminate(pid, &status)) < 0) {
r = wait_for_terminate(pid, &status);
if (r < 0) {
log_warning("Failed to wait for %s: %s", name, strerror(-r));
return r;
}
@ -4034,7 +4035,6 @@ int wait_for_terminate_and_warn(const char *name, pid_t pid) {
log_warning("%s failed due to unknown reason.", name);
return -EPROTO;
}
_noreturn_ void freeze(void) {