]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
homed: disable event sources before unreffing them
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 8 Mar 2021 10:37:17 +0000 (11:37 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 8 Mar 2021 10:59:09 +0000 (11:59 +0100)
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.

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

index 5643a9a6e43981b7f14c53b5775f1c45c48b27dd..2a58ecbc1a84b3f5f950abb0dba7e5dcb0e35a6f 100644 (file)
@@ -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) {
index f1db828ed0e2ce40334c8e8976ef23a52daae553..5a777e88ef7e4e4a64a4a70d8c2bd210ec408847 100644 (file)
@@ -188,17 +188,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);
 
@@ -888,7 +888,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));
@@ -1067,7 +1067,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;
         }
 
index d3ac98f901ce355f77b08cbc131371257bc3177e..8a06bb62bf76cae80bffee9b61028f0e73bfa071 100644 (file)
@@ -860,7 +860,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,
index fd0be1d56f84294ee48cc3e3afb9218637a28848..2cab414bb39e32248320b938e80d7783d0d8ad54 100644 (file)
@@ -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) {
@@ -1670,7 +1670,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);
@@ -1708,7 +1708,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;