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

Reply via email to