Move the container wait logic into its own wait_for_container() function and add two status codes: CONTAINER_TERMINATED or CONTAINER_REBOOTED
These status codes are used to terminate nspawn or loop again in case of CONTAINER_REBOOTED. --- src/nspawn/nspawn.c | 114 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 39 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 0bd52da..d606bf2 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, @@ -2565,6 +2570,72 @@ static int change_uid_gid(char **_home) { return 0; } +/* Return 0 in case the container is being rebooted, has been shut + * down or exited succesfully. On failures a non-zero 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, k; + siginfo_t status; + + /* Explicitly set this to CONTAINER_TERMINATED. If the reboot + * conditions are met it will be updated to CONTAINER_REBOOTED */ + *container = CONTAINER_TERMINATED; + + r = EXIT_FAILURE; + k = wait_for_terminate(pid, &status); + if (k < 0) + return r; + + 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); + goto out; + } + + if (!arg_quiet) + log_debug("Container %s exited successfully.", + arg_machine); + + } 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 (status.si_code == CLD_KILLED && + status.si_status == SIGHUP) { + + if (!arg_quiet) + log_info("Container %s is being rebooted.", + arg_machine); + r = 0; + *container = CONTAINER_REBOOTED; + + } 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; + + } else { + log_error("Container %s failed due to unknown reason.", + arg_machine); + r = EXIT_FAILURE; + } + +out: + 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; @@ -2743,8 +2814,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); @@ -3094,48 +3165,13 @@ 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) { - 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); + if (r || container_status == CONTAINER_TERMINATED) 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; - 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: -- 1.8.5.3 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel