]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
lxccontainer: switch to pidfd polling when shutting down containers
authorChristian Brauner <christian.brauner@ubuntu.com>
Wed, 11 Mar 2020 14:05:45 +0000 (15:05 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Wed, 11 Mar 2020 14:59:33 +0000 (15:59 +0100)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/lxccontainer.c

index 5dddd14eca707abddc861bfbf0ad57b460eea84a..0c69670aaefcac6ec571cd2718a21b26e5499c17 100644 (file)
@@ -2094,11 +2094,9 @@ static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
                return true;
 
        pidfd = do_lxcapi_init_pidfd(c);
-       if (pidfd < 0) {
-               pid = do_lxcapi_init_pid(c);
-               if (pid <= 0)
-                       return true;
-       }
+       pid = do_lxcapi_init_pid(c);
+       if (pid <= 0)
+               return true;
 
        /* Detect whether we should send SIGRTMIN + 3 (e.g. systemd). */
        if (c->lxc_conf && c->lxc_conf->haltsignal)
@@ -2106,8 +2104,10 @@ static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
        else if (task_blocks_signal(pid, (SIGRTMIN + 3)))
                haltsignal = (SIGRTMIN + 3);
 
-       /* Add a new state client before sending the shutdown signal so that we
-        * don't miss a state.
+
+       /*
+        * Add a new state client before sending the shutdown signal so
+        * that we don't miss a state.
         */
        if (timeout != 0) {
                states[STOPPED] = 1;
@@ -2124,23 +2124,41 @@ static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
 
                if (ret < MAX_STATE)
                        return false;
-       }
 
-       /* Send shutdown signal to container. */
-       if (pidfd >= 0) {
-               killret = lxc_raw_pidfd_send_signal(pidfd, haltsignal, NULL, 0);
-               if (killret < 0)
-                       return log_warn(false, "Failed to send signal %d to pidfd %d",
-                                       haltsignal, pidfd);
+               if (pidfd >= 0) {
+                       struct pollfd pidfd_poll = {
+                           .events = POLLIN,
+                           .fd = pidfd,
+                       };
 
-               TRACE("Sent signal %d to pidfd %d", haltsignal, pidfd);
-       } else {
-               killret = kill(pid, haltsignal);
-               if (killret < 0)
-                       return log_warn(false, "Failed to send signal %d to pid %d",
-                                       haltsignal, pid);
+                       killret = lxc_raw_pidfd_send_signal(pidfd, haltsignal,
+                                                           NULL, 0);
+                       if (killret < 0)
+                               return log_warn(false, "Failed to send signal %d to pidfd %d",
+                                               haltsignal, pidfd);
+
+                       TRACE("Sent signal %d to pidfd %d", haltsignal, pidfd);
+
+                       /*
+                        * No need for going through all of the state server
+                        * complications anymore. We can just poll on pidfds. :)
+                        */
 
-               TRACE("Sent signal %d to pid %d", haltsignal, pid);
+                       if (timeout != 0) {
+                               ret = poll(&pidfd_poll, 1, timeout);
+                               if (ret < 0 || !(pidfd_poll.revents & POLLIN))
+                                       return false;
+
+                               TRACE("Pidfd polling detected container exit");
+                       }
+               } else {
+                       killret = kill(pid, haltsignal);
+                       if (killret < 0)
+                               return log_warn(false, "Failed to send signal %d to pid %d",
+                                               haltsignal, pid);
+
+                       TRACE("Sent signal %d to pid %d", haltsignal, pid);
+               }
        }
 
        if (timeout == 0)