homed: make sure our worker processes finish before we exit

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
This commit is contained in:
Lennart Poettering 2020-09-18 18:53:12 +02:00
parent cc9886bc20
commit 9796a9fbad
3 changed files with 20 additions and 0 deletions

View File

@ -2739,6 +2739,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",

View File

@ -165,5 +165,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);

View File

@ -232,8 +232,13 @@ int manager_new(Manager **ret) {
}
Manager* manager_free(Manager *m) {
Home *h;
assert(m);
HASHMAP_FOREACH(h, m->homes_by_worker_pid)
(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);