diff options
Diffstat (limited to 'src/nspawn/nspawn.c')
-rw-r--r-- | src/nspawn/nspawn.c | 115 |
1 files changed, 78 insertions, 37 deletions
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 73158a0518..0cd476cd9e 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -92,6 +92,11 @@ #include "seccomp-util.h" #endif +typedef enum ContainerStatus { + CONTAINER_TERMINATED, + CONTAINER_REBOOTED +} ContainerStatus; + typedef enum LinkJournal { LINK_NO, LINK_AUTO, @@ -2569,6 +2574,74 @@ static int change_uid_gid(char **_home) { return 0; } +/* + * Return 0 in case the container is being rebooted, has been shut + * down or exited successfully. On failures a negative value is + * returned. + * + * The status of the container "CONTAINER_TERMINATED" or + * "CONTAINER_REBOOTED" will be saved in the container argument + */ +static int wait_for_container(pid_t pid, ContainerStatus *container) { + int r; + siginfo_t status; + + r = wait_for_terminate(pid, &status); + if (r < 0) + return r; + + switch (status.si_code) { + case CLD_EXITED: + r = status.si_status; + if (r == 0) { + if (!arg_quiet) + log_debug("Container %s exited successfully.", + arg_machine); + + *container = CONTAINER_TERMINATED; + } else { + log_error("Container %s failed with error code %i.", + arg_machine, status.si_status); + r = -1; + } + break; + + case CLD_KILLED: + if (status.si_status == SIGINT) { + if (!arg_quiet) + log_info("Container %s has been shut down.", + arg_machine); + + *container = CONTAINER_TERMINATED; + r = 0; + break; + } else if (status.si_status == SIGHUP) { + if (!arg_quiet) + log_info("Container %s is being rebooted.", + arg_machine); + + *container = CONTAINER_REBOOTED; + r = 0; + break; + } + /* CLD_KILLED fallthrough */ + + case CLD_DUMPED: + log_error("Container %s terminated by signal %s.", + arg_machine, signal_to_string(status.si_status)); + r = -1; + break; + + default: + log_error("Container %s failed due to unknown reason.", + arg_machine); + r = -1; + break; + } + + return r; +} + int main(int argc, char *argv[]) { _cleanup_free_ char *kdbus_domain = NULL, *device_path = NULL, *root_device = NULL, *home_device = NULL, *srv_device = NULL; @@ -2747,8 +2820,8 @@ int main(int argc, char *argv[]) { assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0); for (;;) { + ContainerStatus container_status; int parent_ready_fd = -1, child_ready_fd = -1; - siginfo_t status; eventfd_t x; parent_ready_fd = eventfd(0, EFD_CLOEXEC); @@ -3100,48 +3173,16 @@ int main(int argc, char *argv[]) { /* Redundant, but better safe than sorry */ kill(pid, SIGKILL); - k = wait_for_terminate(pid, &status); + r = wait_for_container(pid, &container_status); pid = 0; - if (k < 0) { + if (r < 0) { r = EXIT_FAILURE; break; - } - - if (status.si_code == CLD_EXITED) { - r = status.si_status; - if (status.si_status != 0) { - log_error("Container %s failed with error code %i.", arg_machine, status.si_status); - break; - } - - if (!arg_quiet) - log_debug("Container %s exited successfully.", arg_machine); - break; - } else if (status.si_code == CLD_KILLED && - status.si_status == SIGINT) { - - if (!arg_quiet) - log_info("Container %s has been shut down.", arg_machine); - r = 0; + } else if (container_status == CONTAINER_TERMINATED) break; - } else if (status.si_code == CLD_KILLED && - status.si_status == SIGHUP) { - - if (!arg_quiet) - log_info("Container %s is being rebooted.", arg_machine); - continue; - } else if (status.si_code == CLD_KILLED || - status.si_code == CLD_DUMPED) { - log_error("Container %s terminated by signal %s.", arg_machine, signal_to_string(status.si_status)); - r = EXIT_FAILURE; - break; - } else { - log_error("Container %s failed due to unknown reason.", arg_machine); - r = EXIT_FAILURE; - break; - } + /* CONTAINER_REBOOTED, loop again */ } finish: |