]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: serialize u->pids until the processes have been moved to the scope cgroup
authorFranck Bui <fbui@suse.com>
Mon, 16 Nov 2020 14:12:21 +0000 (15:12 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 20 Nov 2020 14:57:59 +0000 (15:57 +0100)
Otherwise if a daemon-reload happens somewhere between the enqueue of the job
start for the scope unit and scope_start() then u->pids might be lost and none
of the processes specified by "PIDs=" will be moved into the scope cgroup.

src/core/scope.c

index a4db272f93f9b41d495558fe0ea53775e9289234..a372f8d726a947f685b8a1df563551dd6abd8203 100644 (file)
@@ -8,6 +8,7 @@
 #include "dbus-unit.h"
 #include "load-dropin.h"
 #include "log.h"
+#include "process-util.h"
 #include "scope.h"
 #include "serialize.h"
 #include "special.h"
@@ -235,8 +236,18 @@ static int scope_coldplug(Unit *u) {
         if (r < 0)
                 return r;
 
-        if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED))
-                (void) unit_enqueue_rewatch_pids(u);
+        if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED)) {
+                if (u->pids) {
+                        void *pidp;
+
+                        SET_FOREACH(pidp, u->pids) {
+                                r = unit_watch_pid(u, PTR_TO_PID(pidp), false);
+                                if (r < 0 && r != -EEXIST)
+                                        return r;
+                        }
+                } else
+                        (void) unit_enqueue_rewatch_pids(u);
+        }
 
         bus_scope_track_controller(s);
 
@@ -366,6 +377,10 @@ static int scope_start(Unit *u) {
                 return r;
         }
 
+        /* Now u->pids have been moved into the scope cgroup, it's not needed
+         * anymore. */
+        u->pids = set_free(u->pids);
+
         s->result = SCOPE_SUCCESS;
 
         scope_set_state(s, SCOPE_RUNNING);
@@ -427,6 +442,7 @@ static int scope_get_timeout(Unit *u, usec_t *timeout) {
 
 static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
         Scope *s = SCOPE(u);
+        void *pidp;
 
         assert(s);
         assert(f);
@@ -438,6 +454,9 @@ static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
         if (s->controller)
                 (void) serialize_item(f, "controller", s->controller);
 
+        SET_FOREACH(pidp, u->pids)
+                serialize_item_format(f, "pids", PID_FMT, PTR_TO_PID(pidp));
+
         return 0;
 }
 
@@ -473,6 +492,20 @@ static int scope_deserialize_item(Unit *u, const char *key, const char *value, F
                 if (r < 0)
                         return log_oom();
 
+        } else if (streq(key, "pids")) {
+                pid_t pid;
+
+                if (parse_pid(value, &pid) < 0)
+                        log_unit_debug(u, "Failed to parse pids value: %s", value);
+                else {
+                        r = set_ensure_allocated(&u->pids, NULL);
+                        if (r < 0)
+                                return r;
+
+                        r = set_put(u->pids, PID_TO_PTR(pid));
+                        if (r < 0)
+                                return r;
+                }
         } else
                 log_unit_debug(u, "Unknown serialization key: %s", key);