diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2021-03-08 11:37:17 +0100 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2021-03-12 18:22:59 +0100 |
commit | 4e39cf7708c996a679f98a05c5840e9923c0315c (patch) | |
tree | 5a2eb2b0b77d076fd5e08797bd6484c7e294b286 | |
parent | 406494c0a5643ad8807ea7d5671cb9ecd71116e3 (diff) | |
download | systemd-4e39cf7708c996a679f98a05c5840e9923c0315c.tar.gz |
homed: disable event sources before unreffing them
C.f. 9793530228.
We'd crash when trying to access an already-deallocated object:
Thread no. 1 (7 frames)
#2 log_assert_failed_realm at ../src/basic/log.c:844
#3 event_inotify_data_drop at ../src/libsystemd/sd-event/sd-event.c:3035
#4 source_dispatch at ../src/libsystemd/sd-event/sd-event.c:3250
#5 sd_event_dispatch at ../src/libsystemd/sd-event/sd-event.c:3631
#6 sd_event_run at ../src/libsystemd/sd-event/sd-event.c:3689
#7 sd_event_loop at ../src/libsystemd/sd-event/sd-event.c:3711
#8 run at ../src/home/homed.c:47
The source in question is an inotify source, and the messages are:
systemd-homed[1340]: /home/ moved or renamed, recreating watch and rescanning.
systemd-homed[1340]: Assertion '*_head == _item' failed at src/libsystemd/sd-event/sd-event.c:3035, function event_inotify_data_drop(). Aborting.
on_home_inotify() got called, then manager_watch_home(), which unrefs the
existing inotify_event_source. I assume that the source gets dispatched again
because it was still in the pending queue.
I can't reproduce the issue (timing?), but this should
fix #17824, https://bugzilla.redhat.com/show_bug.cgi?id=1899264.
(cherry picked from commit cf5366387b24633284ee92285ea64a282270d591)
(cherry picked from commit 668554d9dbfa9f240dd18455a52c68f3f48bdb81)
-rw-r--r-- | src/home/homed-home-bus.c | 2 | ||||
-rw-r--r-- | src/home/homed-home.c | 14 | ||||
-rw-r--r-- | src/home/homed-manager-bus.c | 2 | ||||
-rw-r--r-- | src/home/homed-manager.c | 6 |
4 files changed, 12 insertions, 12 deletions
diff --git a/src/home/homed-home-bus.c b/src/home/homed-home-bus.c index 6be361a5aa..bc133a51e4 100644 --- a/src/home/homed-home-bus.c +++ b/src/home/homed-home-bus.c @@ -885,7 +885,7 @@ static int on_deferred_change(sd_event_source *s, void *userdata) { assert(h); - h->deferred_change_event_source = sd_event_source_unref(h->deferred_change_event_source); + h->deferred_change_event_source = sd_event_source_disable_unref(h->deferred_change_event_source); r = bus_home_path(h, &path); if (r < 0) { diff --git a/src/home/homed-home.c b/src/home/homed-home.c index c5dfe3d2f2..28c8e701c4 100644 --- a/src/home/homed-home.c +++ b/src/home/homed-home.c @@ -187,17 +187,17 @@ Home *home_free(Home *h) { user_record_unref(h->record); user_record_unref(h->secret); - h->worker_event_source = sd_event_source_unref(h->worker_event_source); + h->worker_event_source = sd_event_source_disable_unref(h->worker_event_source); safe_close(h->worker_stdout_fd); free(h->user_name); free(h->sysfs); - h->ref_event_source_please_suspend = sd_event_source_unref(h->ref_event_source_please_suspend); - h->ref_event_source_dont_suspend = sd_event_source_unref(h->ref_event_source_dont_suspend); + h->ref_event_source_please_suspend = sd_event_source_disable_unref(h->ref_event_source_please_suspend); + h->ref_event_source_dont_suspend = sd_event_source_disable_unref(h->ref_event_source_dont_suspend); h->pending_operations = ordered_set_free(h->pending_operations); - h->pending_event_source = sd_event_source_unref(h->pending_event_source); - h->deferred_change_event_source = sd_event_source_unref(h->deferred_change_event_source); + h->pending_event_source = sd_event_source_disable_unref(h->pending_event_source); + h->deferred_change_event_source = sd_event_source_disable_unref(h->deferred_change_event_source); h->current_operation = operation_unref(h->current_operation); @@ -885,7 +885,7 @@ static int home_on_worker_process(sd_event_source *s, const siginfo_t *si, void (void) hashmap_remove_value(h->manager->homes_by_worker_pid, PID_TO_PTR(h->worker_pid), h); h->worker_pid = 0; - h->worker_event_source = sd_event_source_unref(h->worker_event_source); + h->worker_event_source = sd_event_source_disable_unref(h->worker_event_source); if (si->si_code != CLD_EXITED) { assert(IN_SET(si->si_code, CLD_KILLED, CLD_DUMPED)); @@ -1054,7 +1054,7 @@ static int home_start_work(Home *h, const char *verb, UserRecord *hr, UserRecord r = hashmap_put(h->manager->homes_by_worker_pid, PID_TO_PTR(pid), h); if (r < 0) { - h->worker_event_source = sd_event_source_unref(h->worker_event_source); + h->worker_event_source = sd_event_source_disable_unref(h->worker_event_source); return r; } diff --git a/src/home/homed-manager-bus.c b/src/home/homed-manager-bus.c index ce6919a1a7..4c0158d901 100644 --- a/src/home/homed-manager-bus.c +++ b/src/home/homed-manager-bus.c @@ -824,7 +824,7 @@ static int on_deferred_auto_login(sd_event_source *s, void *userdata) { assert(m); - m->deferred_auto_login_event_source = sd_event_source_unref(m->deferred_auto_login_event_source); + m->deferred_auto_login_event_source = sd_event_source_disable_unref(m->deferred_auto_login_event_source); r = sd_bus_emit_properties_changed( m->bus, diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c index 3b75e2c345..2024ff24ff 100644 --- a/src/home/homed-manager.c +++ b/src/home/homed-manager.c @@ -79,7 +79,7 @@ static void manager_watch_home(Manager *m) { assert(m); - m->inotify_event_source = sd_event_source_unref(m->inotify_event_source); + m->inotify_event_source = sd_event_source_disable_unref(m->inotify_event_source); m->scan_slash_home = false; if (statfs("/home/", &sfs) < 0) { @@ -1636,7 +1636,7 @@ static int on_deferred_rescan(sd_event_source *s, void *userdata) { assert(m); - m->deferred_rescan_event_source = sd_event_source_unref(m->deferred_rescan_event_source); + m->deferred_rescan_event_source = sd_event_source_disable_unref(m->deferred_rescan_event_source); manager_enumerate_devices(m); manager_enumerate_images(m); @@ -1674,7 +1674,7 @@ static int on_deferred_gc(sd_event_source *s, void *userdata) { assert(m); - m->deferred_gc_event_source = sd_event_source_unref(m->deferred_gc_event_source); + m->deferred_gc_event_source = sd_event_source_disable_unref(m->deferred_gc_event_source); manager_gc_images(m); return 0; |