core: whenever we change state of a unit, force out PropertiesChanged bus signal

This allows clients to follow our internal state changes safely.

Previously, quick state changes (for example, when we restart a unit due
to Restart= after it quickly transitioned through DEAD/FAILED states)
would be coalesced into one bus signal event, with this change there's
the guarantee that all state changes after the unit was announced ones
are reflected on th bus.

Note we only do this kind of guaranteed flushing only for unit state
changes, not for other unit property changes, where clients still have
to expect coalescing. This is because the unit state is a very
important, high-level concept.

Fixes: #10185
This commit is contained in:
Lennart Poettering
2018-12-01 12:53:26 +01:00
parent 37d0b962ef
commit 6fcbec6f9b
13 changed files with 66 additions and 0 deletions
+4
View File
@@ -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;
+21
View File
@@ -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;
+1
View File
@@ -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);
+4
View File
@@ -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;
+4
View File
@@ -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;
+4
View File
@@ -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;
+4
View File
@@ -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;
+4
View File
@@ -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;
+4
View File
@@ -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;
+4
View File
@@ -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;
+4
View File
@@ -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;
+4
View File
@@ -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;
+4
View File
@@ -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;