]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
homed: port worker management to PidRef 36557/head
authorLennart Poettering <lennart@poettering.net>
Fri, 28 Feb 2025 08:58:36 +0000 (09:58 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 28 Feb 2025 13:18:23 +0000 (14:18 +0100)
src/home/homed-home.c
src/home/homed-home.h
src/home/homed-manager.c

index eba7be9b6a5b0c75ca4d85bfaee8e2315b1a0dd1..871ccdffe9167f6d22308cf858990dd1e2c6db04 100644 (file)
@@ -12,6 +12,7 @@
 #include "env-util.h"
 #include "errno-list.h"
 #include "errno-util.h"
+#include "event-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "filesystems.h"
@@ -153,6 +154,7 @@ int home_new(Manager *m, UserRecord *hr, const char *sysfs, Home **ret) {
                 .aliases = TAKE_PTR(aliases),
                 .uid = hr->uid,
                 .state = _HOME_STATE_INVALID,
+                .worker_pid = PIDREF_NULL,
                 .worker_stdout_fd = -EBADF,
                 .sysfs = TAKE_PTR(ns),
                 .signed_locally = -1,
@@ -224,8 +226,8 @@ Home *home_free(Home *h) {
                 if (h->sysfs)
                         (void) hashmap_remove_value(h->manager->homes_by_sysfs, h->sysfs, h);
 
-                if (h->worker_pid > 0)
-                        (void) hashmap_remove_value(h->manager->homes_by_worker_pid, PID_TO_PTR(h->worker_pid), h);
+                if (pidref_is_set(&h->worker_pid))
+                        (void) hashmap_remove_value(h->manager->homes_by_worker_pid, &h->worker_pid, h);
 
                 if (h->manager->gc_focus == h)
                         h->manager->gc_focus = NULL;
@@ -236,6 +238,7 @@ Home *home_free(Home *h) {
         user_record_unref(h->record);
         user_record_unref(h->secret);
 
+        pidref_done_sigkill_wait(&h->worker_pid);
         h->worker_event_source = sd_event_source_disable_unref(h->worker_event_source);
         safe_close(h->worker_stdout_fd);
         free(h->user_name);
@@ -1137,13 +1140,13 @@ static int home_on_worker_process(sd_event_source *s, const siginfo_t *si, void
         assert(s);
         assert(si);
 
-        assert(h->worker_pid == si->si_pid);
+        assert(h->worker_pid.pid == si->si_pid);
         assert(h->worker_event_source);
         assert(h->worker_stdout_fd >= 0);
 
-        (void) hashmap_remove_value(h->manager->homes_by_worker_pid, PID_TO_PTR(h->worker_pid), h);
+        (void) hashmap_remove_value(h->manager->homes_by_worker_pid, &h->worker_pid, h);
 
-        h->worker_pid = 0;
+        pidref_done(&h->worker_pid);
         h->worker_event_source = sd_event_source_disable_unref(h->worker_event_source);
 
         if (si->si_code != CLD_EXITED) {
@@ -1227,14 +1230,13 @@ static int home_start_work(
         _cleanup_(erase_and_freep) char *formatted = NULL;
         _cleanup_close_ int stdin_fd = -EBADF, stdout_fd = -EBADF;
         _cleanup_free_ int *blob_fds = NULL;
-        pid_t pid = 0;
         int r;
 
         assert(h);
         assert(verb);
         assert(hr);
 
-        if (h->worker_pid != 0)
+        if (pidref_is_set(&h->worker_pid))
                 return -EBUSY;
 
         assert(h->worker_stdout_fd < 0);
@@ -1299,7 +1301,8 @@ static int home_start_work(
         if (stdout_fd < 0)
                 return stdout_fd;
 
-        r = safe_fork_full("(sd-homework)",
+        _cleanup_(pidref_done_sigkill_wait) PidRef pid = PIDREF_NULL;
+        r = pidref_safe_fork_full("(sd-homework)",
                            (int[]) { stdin_fd, stdout_fd, STDERR_FILENO },
                            blob_fds, hashmap_size(blobs),
                            FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_CLOEXEC_OFF|FORK_PACK_FDS|FORK_DEATHSIG_SIGTERM|
@@ -1362,20 +1365,21 @@ static int home_start_work(
                 _exit(EXIT_FAILURE);
         }
 
-        r = sd_event_add_child(h->manager->event, &h->worker_event_source, pid, WEXITED, home_on_worker_process, h);
+        r = event_add_child_pidref(h->manager->event, &h->worker_event_source, &pid, WEXITED, home_on_worker_process, h);
         if (r < 0)
                 return r;
 
         (void) sd_event_source_set_description(h->worker_event_source, "worker");
 
-        r = hashmap_put(h->manager->homes_by_worker_pid, PID_TO_PTR(pid), h);
+        h->worker_pid = TAKE_PIDREF(pid);
+        r = hashmap_put(h->manager->homes_by_worker_pid, &h->worker_pid, h);
         if (r < 0) {
+                pidref_done_sigkill_wait(&h->worker_pid);
                 h->worker_event_source = sd_event_source_disable_unref(h->worker_event_source);
                 return r;
         }
 
         h->worker_stdout_fd = TAKE_FD(stdout_fd);
-        h->worker_pid = pid;
         h->worker_error_code = 0;
 
         return 0;
@@ -3278,19 +3282,19 @@ int home_wait_for_worker(Home *h) {
 
         assert(h);
 
-        if (h->worker_pid <= 0)
+        if (!pidref_is_set(&h->worker_pid))
                 return 0;
 
         log_info("Worker process for home %s is still running while exiting. Waiting for it to finish.", h->user_name);
 
-        r = wait_for_terminate_with_timeout(h->worker_pid, 30 * USEC_PER_SEC);
+        r = wait_for_terminate_with_timeout(h->worker_pid.pid, 30 * USEC_PER_SEC);
         if (r == -ETIMEDOUT)
                 log_warning_errno(r, "Waiting for worker process for home %s timed out. Ignoring.", h->user_name);
         else if (r < 0)
                 log_warning_errno(r, "Failed to wait for worker process for home %s. Ignoring.", h->user_name);
 
-        (void) hashmap_remove_value(h->manager->homes_by_worker_pid, PID_TO_PTR(h->worker_pid), h);
-        h->worker_pid = 0;
+        (void) hashmap_remove_value(h->manager->homes_by_worker_pid, &h->worker_pid, h);
+        pidref_done(&h->worker_pid);
         return 1;
 }
 
index 93689563d32d1a4c917abc1936596c0b42b27c60..dfd64461fc8f9cfd8ff4a7f35f6a705f51300d1e 100644 (file)
@@ -8,6 +8,7 @@ typedef struct Home Home;
 #include "homed-operation.h"
 #include "list.h"
 #include "ordered-set.h"
+#include "pidref.h"
 #include "stat-util.h"
 #include "user-record.h"
 
@@ -128,7 +129,7 @@ struct Home {
 
         UserRecord *record;
 
-        pid_t worker_pid;
+        PidRef worker_pid;
         int worker_stdout_fd;
         sd_event_source *worker_event_source;
         int worker_error_code;
index 938468758787135a91457e7660abdbe95453db12..e628e1a389e457d4b812a4eec749651fab305f97 100644 (file)
@@ -77,7 +77,7 @@ static bool uid_is_home(uid_t uid) {
 #define UID_CLAMP_INTO_HOME_RANGE(rnd) (((uid_t) (rnd) % (HOME_UID_MAX - HOME_UID_MIN + 1)) + HOME_UID_MIN)
 
 DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_uid_hash_ops, void, trivial_hash_func, trivial_compare_func, Home, home_free);
-DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_worker_pid_hash_ops, void, trivial_hash_func, trivial_compare_func, Home, home_free);
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_worker_pid_hash_ops, PidRef, pidref_hash_func, pidref_compare_func, Home, home_free);
 DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_sysfs_hash_ops, char, path_hash_func, path_compare, Home, home_free);
 
 static int on_home_inotify(sd_event_source *s, const struct inotify_event *event, void *userdata);
@@ -1089,7 +1089,7 @@ static int on_notify_socket(sd_event_source *s, int fd, uint32_t revents, void *
                 return 0;
         }
 
-        Home *h = hashmap_get(m->homes_by_worker_pid, PID_TO_PTR(sender.pid));
+        Home *h = hashmap_get(m->homes_by_worker_pid, &sender);
         if (!h) {
                 log_warning("Received notify datagram of unknown process, ignoring.");
                 return 0;