]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
pid1: serialize pidrefs as pidfds if possible
authorLennart Poettering <lennart@poettering.net>
Thu, 5 Oct 2023 10:45:38 +0000 (12:45 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 5 Oct 2023 10:57:05 +0000 (12:57 +0200)
One major step towards total pidfdification of systemd.

src/core/mount.c
src/core/scope.c
src/core/service.c
src/core/socket.c
src/core/swap.c
src/core/unit.c
src/core/unit.h
src/shared/serialize.c
src/shared/serialize.h

index 55e0c2ec8863ae35fec50e29a4b67da9bffcd867..6424c56ed32ba4ef21fb9e813cef16fe32303655 100644 (file)
@@ -1405,9 +1405,7 @@ static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
         (void) serialize_item(f, "result", mount_result_to_string(m->result));
         (void) serialize_item(f, "reload-result", mount_result_to_string(m->reload_result));
         (void) serialize_item_format(f, "n-retry-umount", "%u", m->n_retry_umount);
-
-        if (pidref_is_set(&m->control_pid))
-                (void) serialize_item_format(f, "control-pid", PID_FMT, m->control_pid.pid);
+        (void) serialize_pidref(f, fds, "control-pid", &m->control_pid);
 
         if (m->control_command_id >= 0)
                 (void) serialize_item(f, "control-command", mount_exec_command_to_string(m->control_command_id));
@@ -1461,9 +1459,7 @@ static int mount_deserialize_item(Unit *u, const char *key, const char *value, F
         } else if (streq(key, "control-pid")) {
 
                 pidref_done(&m->control_pid);
-                r = pidref_set_pidstr(&m->control_pid, value);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to set control PID to '%s': %m", value);
+                (void) deserialize_pidref(fds, value, &m->control_pid);
 
         } else if (streq(key, "control-command")) {
                 MountExecCommand id;
index 69ac20e53c177ac9963eb97b4c97251fec6c14be..e4c27da91d23541122cef739219ce36eb8677c86 100644 (file)
@@ -546,7 +546,7 @@ static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
                 (void) serialize_item(f, "controller", s->controller);
 
         SET_FOREACH(pid, u->pids)
-                serialize_item_format(f, "pids", PID_FMT, pid->pid);
+                serialize_pidref(f, fds, "pids", pid);
 
         return 0;
 }
@@ -584,10 +584,13 @@ static int scope_deserialize_item(Unit *u, const char *key, const char *value, F
                         return log_oom();
 
         } else if (streq(key, "pids")) {
+                _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
 
-                r = unit_watch_pid_str(u, value, /* exclusive= */ false);
-                if (r < 0)
-                        log_unit_debug(u, "Failed to parse pids value, ignoring: %s", value);
+                if (deserialize_pidref(fds, value, &pidref) >= 0) {
+                        r = unit_watch_pidref(u, &pidref, /* exclusive= */ false);
+                        if (r < 0)
+                                log_unit_debug(u, "Failed to watch PID, ignoring: %s", value);
+                }
         } else
                 log_unit_debug(u, "Unknown serialization key: %s", key);
 
index 8dc98813502eaeed39f8bef5288136013d45d084..73a678b0cc1d3baad7dfda8970734a40796968f1 100644 (file)
@@ -213,19 +213,6 @@ static int service_set_main_pidref(Service *s, PidRef *pidref) {
         return 0;
 }
 
-static int service_set_main_pid(Service *s, pid_t pid) {
-        _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
-        int r;
-
-        assert(s);
-
-        r = pidref_set_pid(&pidref, pid);
-        if (r < 0)
-                return r;
-
-        return service_set_main_pidref(s, &pidref);
-}
-
 void service_release_socket_fd(Service *s) {
         assert(s);
 
@@ -2949,11 +2936,9 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
         (void) serialize_item(f, "result", service_result_to_string(s->result));
         (void) serialize_item(f, "reload-result", service_result_to_string(s->reload_result));
 
-        if (pidref_is_set(&s->control_pid))
-                (void) serialize_item_format(f, "control-pid", PID_FMT, s->control_pid.pid);
-
-        if (s->main_pid_known && pidref_is_set(&s->main_pid))
-                (void) serialize_item_format(f, "main-pid", PID_FMT, s->main_pid.pid);
+        (void) serialize_pidref(f, fds, "control-pid", &s->control_pid);
+        if (s->main_pid_known)
+                (void) serialize_pidref(f, fds, "main-pid", &s->main_pid);
 
         (void) serialize_bool(f, "main-pid-known", s->main_pid_known);
         (void) serialize_bool(f, "bus-name-good", s->bus_name_good);
@@ -3188,16 +3173,15 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
 
         } else if (streq(key, "control-pid")) {
                 pidref_done(&s->control_pid);
-                r = pidref_set_pidstr(&s->control_pid, value);
-                if (r < 0)
-                        log_unit_debug_errno(u, r, "Failed to initialize control PID '%s' from serialization, ignoring.", value);
+
+                (void) deserialize_pidref(fds, value, &s->control_pid);
+
         } else if (streq(key, "main-pid")) {
-                pid_t pid;
+                _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
+
+                if (deserialize_pidref(fds, value, &pidref) >= 0)
+                        (void) service_set_main_pidref(s, &pidref);
 
-                if (parse_pid(value, &pid) < 0)
-                        log_unit_debug(u, "Failed to parse main-pid value: %s", value);
-                else
-                        (void) service_set_main_pid(s, pid);
         } else if (streq(key, "main-pid-known")) {
                 int b;
 
index e5b2e8ae762ac2bddc8618323372b00609d6b508..1bbcadc3ba3008b84bcdcedd87cb9f708fb7dcaf 100644 (file)
@@ -2557,9 +2557,7 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
         (void) serialize_item(f, "result", socket_result_to_string(s->result));
         (void) serialize_item_format(f, "n-accepted", "%u", s->n_accepted);
         (void) serialize_item_format(f, "n-refused", "%u", s->n_refused);
-
-        if (pidref_is_set(&s->control_pid))
-                (void) serialize_item_format(f, "control-pid", PID_FMT, s->control_pid.pid);
+        (void) serialize_pidref(f, fds, "control-pid", &s->control_pid);
 
         if (s->control_command_id >= 0)
                 (void) serialize_item(f, "control-command", socket_exec_command_to_string(s->control_command_id));
@@ -2641,9 +2639,8 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
                         s->n_refused += k;
         } else if (streq(key, "control-pid")) {
                 pidref_done(&s->control_pid);
-                r = pidref_set_pidstr(&s->control_pid, value);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to pin control PID '%s', ignoring: %m", value);
+                (void) deserialize_pidref(fds, value, &s->control_pid);
+
         } else if (streq(key, "control-command")) {
                 SocketExecCommand id;
 
index 8a6a32543a905c85d10c1a7fe12e5c233a4f7bf2..008c5bbc247a180b6656d6094c85e84306256b46 100644 (file)
@@ -962,9 +962,7 @@ static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
 
         (void) serialize_item(f, "state", swap_state_to_string(s->state));
         (void) serialize_item(f, "result", swap_result_to_string(s->result));
-
-        if (pidref_is_set(&s->control_pid))
-                (void) serialize_item_format(f, "control-pid", PID_FMT, s->control_pid.pid);
+        (void) serialize_pidref(f, fds, "control-pid", &s->control_pid);
 
         if (s->control_command_id >= 0)
                 (void) serialize_item(f, "control-command", swap_exec_command_to_string(s->control_command_id));
@@ -974,7 +972,6 @@ static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
 
 static int swap_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
         Swap *s = SWAP(u);
-        int r;
 
         assert(s);
         assert(fds);
@@ -998,9 +995,7 @@ static int swap_deserialize_item(Unit *u, const char *key, const char *value, FD
         } else if (streq(key, "control-pid")) {
 
                 pidref_done(&s->control_pid);
-                r = pidref_set_pidstr(&s->control_pid, value);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to pin control PID '%s', ignoring: %m", value);
+                (void) deserialize_pidref(fds, value, &s->control_pid);
 
         } else if (streq(key, "control-command")) {
                 SwapExecCommand id;
index ea49cfa504f37f652c6782f5fdbfcc04c3421538..70a4f8403668884cab64930ba30150149b182efc 100644 (file)
@@ -2918,20 +2918,6 @@ int unit_watch_pid(Unit *u, pid_t pid, bool exclusive) {
         return unit_watch_pidref(u, &pidref, exclusive);
 }
 
-int unit_watch_pid_str(Unit *u, const char *s, bool exclusive) {
-        _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
-        int r;
-
-        assert(u);
-        assert(s);
-
-        r = pidref_set_pidstr(&pidref, s);
-        if (r < 0)
-                return r;
-
-        return unit_watch_pidref(u, &pidref, exclusive);
-}
-
 void unit_unwatch_pidref(Unit *u, PidRef *pid) {
         assert(u);
         assert(pidref_is_set(pid));
index b39d868f869579180d54c4a23955e5fa142c2e6f..a95aec345fb2c96a1376b5416f549b74cfe9749c 100644 (file)
@@ -921,7 +921,6 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
 
 int unit_watch_pidref(Unit *u, PidRef *pid, bool exclusive);
 int unit_watch_pid(Unit *u, pid_t pid, bool exclusive);
-int unit_watch_pid_str(Unit *u, const char *s, bool exclusive);
 void unit_unwatch_pidref(Unit *u, PidRef *pid);
 void unit_unwatch_pid(Unit *u, pid_t pid);
 void unit_unwatch_all_pids(Unit *u);
index f9795efe367d29ba06f9e102ad9ef454ff37c2d3..2ffc524f15d696daf684228064f5dbc219a18d87 100644 (file)
@@ -5,6 +5,7 @@
 #include "alloc-util.h"
 #include "env-util.h"
 #include "escape.h"
+#include "fd-util.h"
 #include "fileio.h"
 #include "memfd-util.h"
 #include "missing_mman.h"
@@ -101,6 +102,7 @@ int serialize_fd(FILE *f, FDSet *fds, const char *key, int fd) {
         int copy;
 
         assert(f);
+        assert(fds);
         assert(key);
 
         if (fd < 0)
@@ -149,6 +151,28 @@ int serialize_strv(FILE *f, const char *key, char **l) {
         return ret;
 }
 
+int serialize_pidref(FILE *f, FDSet *fds, const char *key, PidRef *pidref) {
+        int copy;
+
+        assert(f);
+        assert(fds);
+
+        if (!pidref_is_set(pidref))
+                return 0;
+
+        /* If we have a pidfd we serialize the fd and encode the fd number prefixed by "@" in the
+         * serialization. Otherwise we serialize the numeric PID as it is. */
+
+        if (pidref->fd < 0)
+                return serialize_item_format(f, key, PID_FMT, pidref->pid);
+
+        copy = fdset_put_dup(fds, pidref->fd);
+        if (copy < 0)
+                return log_error_errno(copy, "Failed to add file descriptor to serialization set: %m");
+
+        return serialize_item_format(f, key, "@%i", copy);
+}
+
 int deserialize_read_line(FILE *f, char **ret) {
         _cleanup_free_ char *line = NULL;
         int r;
@@ -255,6 +279,42 @@ int deserialize_environment(const char *value, char ***list) {
         return 0;
 }
 
+int deserialize_pidref(FDSet *fds, const char *value, PidRef *ret) {
+        const char *e;
+        int r;
+
+        assert(value);
+        assert(ret);
+
+        e = startswith(value, "@");
+        if (e) {
+                _cleanup_close_ int our_fd = -EBADF;
+                int parsed_fd;
+
+                parsed_fd = parse_fd(e);
+                if (parsed_fd < 0)
+                        return log_debug_errno(parsed_fd, "Failed to parse file descriptor specification: %s", e);
+
+                our_fd = fdset_remove(fds, parsed_fd); /* Take possession of the fd */
+                if (our_fd < 0)
+                        return log_debug_errno(our_fd, "Failed to acquire pidfd from serialization fds: %m");
+
+                r = pidref_set_pidfd_consume(ret, TAKE_FD(our_fd));
+        } else {
+                pid_t pid;
+
+                r = parse_pid(value, &pid);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to parse PID: %s", value);
+
+                r = pidref_set_pid(ret, pid);
+        }
+        if (r < 0)
+                return log_debug_errno(r, "Failed to initialize pidref: %m");
+
+        return 0;
+}
+
 int open_serialization_fd(const char *ident) {
         int fd;
 
index fa1731acb57f75e7abea0ef8e12cba47cec34b7d..9463d1127cf448c9b09b570fb684d8e91ec09963 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "fdset.h"
 #include "macro.h"
+#include "pidref.h"
 #include "string-util.h"
 #include "time-util.h"
 
@@ -15,6 +16,7 @@ int serialize_fd(FILE *f, FDSet *fds, const char *key, int fd);
 int serialize_usec(FILE *f, const char *key, usec_t usec);
 int serialize_dual_timestamp(FILE *f, const char *key, const dual_timestamp *t);
 int serialize_strv(FILE *f, const char *key, char **l);
+int serialize_pidref(FILE *f, FDSet *fds, const char *key, PidRef *pidref);
 
 static inline int serialize_bool(FILE *f, const char *key, bool b) {
         return serialize_item(f, key, yes_no(b));
@@ -29,5 +31,6 @@ int deserialize_usec(const char *value, usec_t *timestamp);
 int deserialize_dual_timestamp(const char *value, dual_timestamp *t);
 int deserialize_environment(const char *value, char ***environment);
 int deserialize_strv(char ***l, const char *value);
+int deserialize_pidref(FDSet *fds, const char *value, PidRef *ret);
 
 int open_serialization_fd(const char *ident);