homed: make sure our worker processes finish before we exit
authorLennart Poettering <lennart@poettering.net>
Fri, 18 Sep 2020 16:53:12 +0000 (18:53 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 20 Sep 2020 10:09:59 +0000 (12:09 +0200)
When exiting, let's explicitly wait for our worker processes to finish
first. That's useful if unmounting of /home/ is scheduled to happen
right after homed is down, as we then can be sure that the home
directories are properly unmounted and detached by the time homed is
fully terminated (otherwise it might happen that our worker gets killed
by the service manager, thus leaving the home directory and its backing
devices up/left for auto-clean which might be async).

Likely fixes #16842

(cherry picked from commit 9796a9fbad5bae4d66bb40d848f6245d1ee327d8)

src/home/homed-home.c
src/home/homed-home.h
src/home/homed-manager.c

index a87fd9a5d027b61f5c4ffef006463dffcaab72f6..b124a3e5d908b456149ed57e46280e7cb573fa2f 100644 (file)
@@ -2709,6 +2709,19 @@ int home_set_current_message(Home *h, sd_bus_message *m) {
         return 1;
 }
 
+int home_wait_for_worker(Home *h) {
+        assert(h);
+
+        if (h->worker_pid <= 0)
+                return 0;
+
+        log_info("Worker process for home %s is still running while exiting. Waiting for it to finish.", h->user_name);
+        (void) wait_for_terminate(h->worker_pid, NULL);
+        (void) hashmap_remove_value(h->manager->homes_by_worker_pid, PID_TO_PTR(h->worker_pid), h);
+        h->worker_pid = 0;
+        return 1;
+}
+
 static const char* const home_state_table[_HOME_STATE_MAX] = {
         [HOME_UNFIXATED]                   = "unfixated",
         [HOME_ABSENT]                      = "absent",
index ec7966fb14bd49b9c5301e7f6f0e0c003c46e447..3bb455f33d216d6d04443c22f65af765b7b8d40b 100644 (file)
@@ -164,5 +164,7 @@ int home_auto_login(Home *h, char ***ret_seats);
 
 int home_set_current_message(Home *h, sd_bus_message *m);
 
+int home_wait_for_worker(Home *h);
+
 const char *home_state_to_string(HomeState state);
 HomeState home_state_from_string(const char *s);
index 54761175c30af62dd5c5dd6e89427db5e20a1f19..6c7c8ebcd944b4ef6a76b09f67726c99a0c96498 100644 (file)
@@ -232,8 +232,14 @@ int manager_new(Manager **ret) {
 }
 
 Manager* manager_free(Manager *m) {
+        Home *h;
+        Iterator i;
+
         assert(m);
 
+        HASHMAP_FOREACH(h, m->homes_by_worker_pid, i)
+                (void) home_wait_for_worker(h);
+
         hashmap_free(m->homes_by_uid);
         hashmap_free(m->homes_by_name);
         hashmap_free(m->homes_by_worker_pid);