[systemd-devel] [PATCH v2] nspawn: move container wait logic into wait_for_container()

Djalal Harouni tixxdz at opendz.org
Fri May 2 04:05:14 PDT 2014


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.
---
v1 -> v2:
Apply Tom Gundersen notes.

src/nspawn/nspawn.c | 113 +++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 76 insertions(+), 37 deletions(-)

diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 0bd52da..5bd2b34 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 successfully. 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;
+        siginfo_t status;
+
+        r = wait_for_terminate(pid, &status);
+        if (r < 0)
+                return r;
+
+        /* If the reboot conditions are met it will be updated to
+         * CONTAINER_REBOOTED, otherwise on all success or failure
+         * paths, the container is put in the CONTAINER_TERMINATED
+         * state. */
+        *container = CONTAINER_TERMINATED;
+
+        switch (status.si_code) {
+        case CLD_EXITED:
+                r = status.si_status;
+                if (r != 0) {
+                        log_error("Container %s failed with error code %i.",
+                                  arg_machine, status.si_status);
+                        r = -1;
+                } else if (!arg_quiet) {
+                        log_debug("Container %s exited successfully.",
+                                  arg_machine);
+                }
+                break;
+
+        case CLD_KILLED:
+                if (status.si_status == SIGINT) {
+                        if (!arg_quiet)
+                                log_info("Container %s has been shut down.",
+                                         arg_machine);
+                        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;
+                }
+
+        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;
@@ -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,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);
+                } else if (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.9.0



More information about the systemd-devel mailing list