From 3b0103aaa563fd038f9a4821b811513e94a91f55 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 28 Feb 2025 09:58:36 +0100 Subject: [PATCH] homed: port worker management to PidRef --- src/home/homed-home.c | 34 +++++++++++++++++++--------------- src/home/homed-home.h | 3 ++- src/home/homed-manager.c | 4 ++-- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/home/homed-home.c b/src/home/homed-home.c index eba7be9b6a5..871ccdffe91 100644 --- a/src/home/homed-home.c +++ b/src/home/homed-home.c @@ -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; } diff --git a/src/home/homed-home.h b/src/home/homed-home.h index 93689563d32..dfd64461fc8 100644 --- a/src/home/homed-home.h +++ b/src/home/homed-home.h @@ -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; diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c index 93846875878..e628e1a389e 100644 --- a/src/home/homed-manager.c +++ b/src/home/homed-manager.c @@ -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; -- 2.47.3