diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 839b1676c8..34643b242c 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -3319,6 +3319,8 @@ static int on_cgroup_oom_event(sd_event_source *s, void *userdata) { } (void) unit_check_oom(u); + unit_add_to_gc_queue(u); + return 0; } diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c index 9792a5c44a..c88d8c2dd5 100644 --- a/src/core/dbus-job.c +++ b/src/core/dbus-job.c @@ -241,6 +241,9 @@ void bus_job_send_change_signal(Job *j) { if (j->in_dbus_queue) { LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j); j->in_dbus_queue = false; + + /* The job might be good to be GC once its pending signals have been sent */ + job_add_to_gc_queue(j); } r = bus_foreach_bus(j->manager, j->bus_track, j->sent_dbus_new_signal ? send_changed_signal : send_new_signal, j); diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 59d541ebfe..629f08ebcc 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -1648,6 +1648,9 @@ void bus_unit_send_change_signal(Unit *u) { if (u->in_dbus_queue) { LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u); u->in_dbus_queue = false; + + /* The unit might be good to be GC once its pending signals have been sent */ + unit_add_to_gc_queue(u); } if (!u->id) diff --git a/src/core/job.c b/src/core/job.c index f87b0f7c74..50f9581d72 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -1444,6 +1444,10 @@ bool job_may_gc(Job *j) { if (!UNIT_VTABLE(j->unit)->gc_jobs) return false; + /* Make sure to send out pending D-Bus events before we unload the unit */ + if (j->in_dbus_queue) + return false; + if (sd_bus_track_count(j->bus_track) > 0) return false; diff --git a/src/core/unit.c b/src/core/unit.c index 7b6d50e0ea..7b2e8c5f5c 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -441,7 +441,14 @@ bool unit_may_gc(Unit *u) { if (u->perpetual) return false; - if (u->in_cgroup_empty_queue) + /* if we saw a cgroup empty event for this unit, stay around until we processed it so that we remove + * the empty cgroup if possible. Similar, process any pending OOM events if they are already queued + * before we release the unit. */ + if (u->in_cgroup_empty_queue || u->in_cgroup_oom_queue) + return false; + + /* Make sure to send out D-Bus events before we unload the unit */ + if (u->in_dbus_queue) return false; if (sd_bus_track_count(u->bus_track) > 0)