diff --git a/src/core/automount.c b/src/core/automount.c index 3d8348e0b7..de8010bf2e 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -16,6 +16,7 @@ #include "bus-error.h" #include "bus-util.h" #include "dbus-automount.h" +#include "dbus-unit.h" #include "fd-util.h" #include "format-util.h" #include "io-util.h" @@ -237,6 +238,9 @@ static void automount_set_state(Automount *a, AutomountState state) { AutomountState old_state; assert(a); + if (a->state != state) + bus_unit_send_pending_change_signal(UNIT(a), false); + old_state = a->state; a->state = state; diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 6d9b559d2c..4cf7364c50 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -1202,6 +1202,27 @@ void bus_unit_send_change_signal(Unit *u) { u->sent_dbus_new_signal = true; } +void bus_unit_send_pending_change_signal(Unit *u, bool including_new) { + + /* Sends out any pending change signals, but only if they really are pending. This call is used when we are + * about to change state in order to force out a PropertiesChanged signal beforehand if there was one pending + * so that clients can follow the full state transition */ + + if (!u->in_dbus_queue) /* If not enqueued, don't bother */ + return; + + if (!u->sent_dbus_new_signal && !including_new) /* If the unit was never announced, don't bother, it's fine if + * the unit appears in the new state right-away (except if the + * caller explicitly asked us to send it anyway) */ + return; + + if (MANAGER_IS_RELOADING(u->manager)) /* Don't generate unnecessary PropertiesChanged signals for the same unit + * when we are reloading. */ + return; + + bus_unit_send_change_signal(u); +} + static int send_removed_signal(sd_bus *bus, void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_free_ char *p = NULL; diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h index 68eb621836..345345e3eb 100644 --- a/src/core/dbus-unit.h +++ b/src/core/dbus-unit.h @@ -11,6 +11,7 @@ extern const sd_bus_vtable bus_unit_vtable[]; extern const sd_bus_vtable bus_unit_cgroup_vtable[]; void bus_unit_send_change_signal(Unit *u); +void bus_unit_send_pending_change_signal(Unit *u, bool including_new); void bus_unit_send_removed_signal(Unit *u); int bus_unit_method_start_generic(sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible, sd_bus_error *error); diff --git a/src/core/device.c b/src/core/device.c index 8b6126c4cf..5acd9b7a70 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -6,6 +6,7 @@ #include "alloc-util.h" #include "bus-error.h" #include "dbus-device.h" +#include "dbus-unit.h" #include "device-private.h" #include "device-util.h" #include "device.h" @@ -115,6 +116,9 @@ static void device_set_state(Device *d, DeviceState state) { DeviceState old_state; assert(d); + if (d->state != state) + bus_unit_send_pending_change_signal(UNIT(d), false); + old_state = d->state; d->state = state; diff --git a/src/core/mount.c b/src/core/mount.c index 99b2aa0904..afdbaa1d9d 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -11,6 +11,7 @@ #include "alloc-util.h" #include "dbus-mount.h" +#include "dbus-unit.h" #include "device.h" #include "escape.h" #include "exit-status.h" @@ -640,6 +641,9 @@ static void mount_set_state(Mount *m, MountState state) { MountState old_state; assert(m); + if (m->state != state) + bus_unit_send_pending_change_signal(UNIT(m), false); + old_state = m->state; m->state = state; diff --git a/src/core/path.c b/src/core/path.c index 01019b0cf7..831e49df29 100644 --- a/src/core/path.c +++ b/src/core/path.c @@ -8,6 +8,7 @@ #include "bus-error.h" #include "bus-util.h" #include "dbus-path.h" +#include "dbus-unit.h" #include "fd-util.h" #include "fs-util.h" #include "glob-util.h" @@ -410,6 +411,9 @@ static void path_set_state(Path *p, PathState state) { PathState old_state; assert(p); + if (p->state != state) + bus_unit_send_pending_change_signal(UNIT(p), false); + old_state = p->state; p->state = state; diff --git a/src/core/scope.c b/src/core/scope.c index 151b8989a6..e478661f94 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -5,6 +5,7 @@ #include "alloc-util.h" #include "dbus-scope.h" +#include "dbus-unit.h" #include "load-dropin.h" #include "log.h" #include "scope.h" @@ -82,6 +83,9 @@ static void scope_set_state(Scope *s, ScopeState state) { ScopeState old_state; assert(s); + if (s->state != state) + bus_unit_send_pending_change_signal(UNIT(s), false); + old_state = s->state; s->state = state; diff --git a/src/core/service.c b/src/core/service.c index 964a7fd057..76f1e16069 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -12,6 +12,7 @@ #include "bus-kernel.h" #include "bus-util.h" #include "dbus-service.h" +#include "dbus-unit.h" #include "def.h" #include "env-util.h" #include "escape.h" @@ -1035,6 +1036,9 @@ static void service_set_state(Service *s, ServiceState state) { assert(s); + if (s->state != state) + bus_unit_send_pending_change_signal(UNIT(s), false); + table = s->type == SERVICE_IDLE ? state_translation_table_idle : state_translation_table; old_state = s->state; diff --git a/src/core/slice.c b/src/core/slice.c index dc087680e1..15b18bcad3 100644 --- a/src/core/slice.c +++ b/src/core/slice.c @@ -4,6 +4,7 @@ #include "alloc-util.h" #include "dbus-slice.h" +#include "dbus-unit.h" #include "log.h" #include "serialize.h" #include "slice.h" @@ -29,6 +30,9 @@ static void slice_set_state(Slice *t, SliceState state) { SliceState old_state; assert(t); + if (t->state != state) + bus_unit_send_pending_change_signal(UNIT(t), false); + old_state = t->state; t->state = state; diff --git a/src/core/socket.c b/src/core/socket.c index f725c9eb00..d3dc0a3216 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -17,6 +17,7 @@ #include "bus-util.h" #include "copy.h" #include "dbus-socket.h" +#include "dbus-unit.h" #include "def.h" #include "exit-status.h" #include "fd-util.h" @@ -1748,6 +1749,9 @@ static void socket_set_state(Socket *s, SocketState state) { SocketState old_state; assert(s); + if (s->state != state) + bus_unit_send_pending_change_signal(UNIT(s), false); + old_state = s->state; s->state = state; diff --git a/src/core/swap.c b/src/core/swap.c index db806fe0bb..90207a48fa 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -9,6 +9,7 @@ #include "alloc-util.h" #include "dbus-swap.h" +#include "dbus-unit.h" #include "device-private.h" #include "device-util.h" #include "device.h" @@ -480,6 +481,9 @@ static void swap_set_state(Swap *s, SwapState state) { assert(s); + if (s->state != state) + bus_unit_send_pending_change_signal(UNIT(s), false); + old_state = s->state; s->state = state; diff --git a/src/core/target.c b/src/core/target.c index b8b8e32805..421a304c73 100644 --- a/src/core/target.c +++ b/src/core/target.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #include "dbus-target.h" +#include "dbus-unit.h" #include "log.h" #include "serialize.h" #include "special.h" @@ -18,6 +19,9 @@ static void target_set_state(Target *t, TargetState state) { TargetState old_state; assert(t); + if (t->state != state) + bus_unit_send_pending_change_signal(UNIT(t), false); + old_state = t->state; t->state = state; diff --git a/src/core/timer.c b/src/core/timer.c index 1527aab158..d9ba2f76b3 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -6,6 +6,7 @@ #include "bus-error.h" #include "bus-util.h" #include "dbus-timer.h" +#include "dbus-unit.h" #include "fs-util.h" #include "parse-util.h" #include "random-util.h" @@ -247,6 +248,9 @@ static void timer_set_state(Timer *t, TimerState state) { TimerState old_state; assert(t); + if (t->state != state) + bus_unit_send_pending_change_signal(UNIT(t), false); + old_state = t->state; t->state = state;